texture1.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. /* -*- tab-width: 4; -*- */
  2. /* vi: set sw=2 ts=4 expandtab: */
  3. /*
  4. * Copyright 2019-2020 The Khronos Group Inc.
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. /**
  8. * @internal
  9. * @file texture2.c
  10. * @~English
  11. *
  12. * @brief ktxTexture1 implementation. Support for KTX format.
  13. *
  14. * @author Mark Callow, www.edgewise-consulting.com
  15. */
  16. #if defined(_WIN32)
  17. #define _CRT_SECURE_NO_WARNINGS
  18. #endif
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "dfdutils/dfd.h"
  22. #include "ktx.h"
  23. #include "ktxint.h"
  24. #include "filestream.h"
  25. #include "memstream.h"
  26. #include "texture1.h"
  27. #include "unused.h"
  28. #include "gl_format.h"
  29. typedef struct ktxTexture1_private {
  30. ktx_bool_t _needSwap;
  31. } ktxTexture1_private;
  32. struct ktxTexture_vtbl ktxTexture1_vtbl;
  33. struct ktxTexture_vtblInt ktxTexture1_vtblInt;
  34. static KTX_error_code
  35. ktxTexture1_constructCommon(ktxTexture1* This)
  36. {
  37. assert(This != NULL);
  38. This->classId = ktxTexture1_c;
  39. This->vtbl = &ktxTexture1_vtbl;
  40. This->_protected->_vtbl = ktxTexture1_vtblInt;
  41. This->_private = (ktxTexture1_private*)malloc(sizeof(ktxTexture1_private));
  42. if (This->_private == NULL) {
  43. return KTX_OUT_OF_MEMORY;
  44. }
  45. memset(This->_private, 0, sizeof(*This->_private));
  46. return KTX_SUCCESS;
  47. }
  48. /**
  49. * @memberof ktxTexture1 @private
  50. * @copydoc ktxTexture2_construct
  51. */
  52. static KTX_error_code
  53. ktxTexture1_construct(ktxTexture1* This, ktxTextureCreateInfo* createInfo,
  54. ktxTextureCreateStorageEnum storageAllocation)
  55. {
  56. ktxTexture_protected* prtctd;
  57. ktxFormatSize formatSize;
  58. GLuint typeSize;
  59. GLenum glFormat;
  60. KTX_error_code result;
  61. memset(This, 0, sizeof(*This));
  62. This->glInternalformat = createInfo->glInternalformat;
  63. glGetFormatSize(This->glInternalformat, &formatSize);
  64. if (formatSize.blockSizeInBits == 0) {
  65. // Most likely a deprecated legacy format.
  66. return KTX_UNSUPPORTED_TEXTURE_TYPE;
  67. }
  68. glFormat= glGetFormatFromInternalFormat(createInfo->glInternalformat);
  69. if (glFormat == GL_INVALID_VALUE) {
  70. return KTX_INVALID_VALUE;
  71. }
  72. result = ktxTexture_construct(ktxTexture(This), createInfo, &formatSize);
  73. if (result != KTX_SUCCESS)
  74. return result;
  75. result = ktxTexture1_constructCommon(This);
  76. if (result != KTX_SUCCESS)
  77. return result;
  78. prtctd = This->_protected;
  79. This->isCompressed
  80. = (formatSize.flags & KTX_FORMAT_SIZE_COMPRESSED_BIT);
  81. if (This->isCompressed) {
  82. This->glFormat = 0;
  83. This->glBaseInternalformat = glFormat;
  84. This->glType = 0;
  85. prtctd->_typeSize = 1;
  86. } else {
  87. This->glBaseInternalformat = This->glFormat = glFormat;
  88. This->glType
  89. = glGetTypeFromInternalFormat(createInfo->glInternalformat);
  90. if (This->glType == GL_INVALID_VALUE) {
  91. result = KTX_INVALID_VALUE;
  92. goto cleanup;
  93. }
  94. typeSize = glGetTypeSizeFromType(This->glType);
  95. assert(typeSize != GL_INVALID_VALUE);
  96. /* Do some sanity checking */
  97. if (typeSize != 1 &&
  98. typeSize != 2 &&
  99. typeSize != 4)
  100. {
  101. /* Only 8, 16, and 32-bit types are supported for byte-swapping.
  102. * See UNPACK_SWAP_BYTES & table 8.4 in the OpenGL 4.4 spec.
  103. */
  104. result = KTX_INVALID_VALUE;
  105. goto cleanup;
  106. }
  107. prtctd->_typeSize = typeSize;
  108. }
  109. if (storageAllocation == KTX_TEXTURE_CREATE_ALLOC_STORAGE) {
  110. This->dataSize
  111. = ktxTexture_calcDataSizeTexture(ktxTexture(This));
  112. This->pData = malloc(This->dataSize);
  113. if (This->pData == NULL) {
  114. result = KTX_OUT_OF_MEMORY;
  115. goto cleanup;
  116. }
  117. }
  118. return result;
  119. cleanup:
  120. ktxTexture1_destruct(This);
  121. ktxTexture_destruct(ktxTexture(This));
  122. return result;
  123. }
  124. /**
  125. * @memberof ktxTexture1 @private
  126. * @brief Construct a ktxTexture1 from a ktxStream reading from a KTX source.
  127. *
  128. * The KTX header, that must have been read prior to calling this, is passed
  129. * to the function.
  130. *
  131. * The stream object is copied into the constructed ktxTexture1.
  132. *
  133. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  134. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  135. * will minimize memory usage by allowing, for example, loading the images
  136. * directly from the source into a Vulkan staging buffer.
  137. *
  138. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  139. * provided solely to enable implementation of the @e libktx v1 API on top of
  140. * ktxTexture1.
  141. *
  142. * @param[in] This pointer to a ktxTexture1-sized block of memory to
  143. * initialize.
  144. * @param[in] pStream pointer to the stream to read.
  145. * @param[in] pHeader pointer to a KTX header that has already been read from
  146. * the stream.
  147. * @param[in] createFlags bitmask requesting specific actions during creation.
  148. *
  149. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  150. *
  151. * @exception KTX_FILE_DATA_ERROR
  152. * Source data is inconsistent with the KTX
  153. * specification.
  154. * @exception KTX_FILE_READ_ERROR
  155. * An error occurred while reading the source.
  156. * @exception KTX_FILE_UNEXPECTED_EOF
  157. * Not enough data in the source.
  158. * @exception KTX_OUT_OF_MEMORY Not enough memory to load either the images or
  159. * the key-value data.
  160. * @exception KTX_UNKNOWN_FILE_FORMAT
  161. * The source is not in KTX format.
  162. * @exception KTX_UNSUPPORTED_TEXTURE_TYPE
  163. * The source describes a texture type not
  164. * supported by OpenGL or Vulkan, e.g, a 3D array.
  165. */
  166. KTX_error_code
  167. ktxTexture1_constructFromStreamAndHeader(ktxTexture1* This, ktxStream* pStream,
  168. KTX_header* pHeader,
  169. ktxTextureCreateFlags createFlags)
  170. {
  171. ktxTexture1_private* private;
  172. KTX_error_code result;
  173. KTX_supplemental_info suppInfo;
  174. ktxStream* stream;
  175. ktx_off_t pos;
  176. ktx_size_t size;
  177. ktxFormatSize formatSize;
  178. assert(pHeader != NULL && pStream != NULL);
  179. memset(This, 0, sizeof(*This));
  180. result = ktxTexture_constructFromStream(ktxTexture(This), pStream, createFlags);
  181. if (result != KTX_SUCCESS)
  182. return result;
  183. result = ktxTexture1_constructCommon(This);
  184. if (result != KTX_SUCCESS) {
  185. ktxTexture_destruct(ktxTexture(This));
  186. return result;
  187. }
  188. private = This->_private;
  189. stream = ktxTexture1_getStream(This);
  190. result = ktxCheckHeader1_(pHeader, &suppInfo);
  191. if (result != KTX_SUCCESS)
  192. goto cleanup;
  193. /*
  194. * Initialize from pHeader info.
  195. */
  196. This->glFormat = pHeader->glFormat;
  197. This->glInternalformat = pHeader->glInternalformat;
  198. This->glType = pHeader->glType;
  199. glGetFormatSize(This->glInternalformat, &formatSize);
  200. if (formatSize.blockSizeInBits == 0) {
  201. // Most likely a deprecated legacy format.
  202. result = KTX_UNSUPPORTED_TEXTURE_TYPE;
  203. goto cleanup;
  204. }
  205. This->_protected->_formatSize = formatSize;
  206. This->glBaseInternalformat = pHeader->glBaseInternalformat;
  207. // Can these be done by a ktxTexture_constructFromStream?
  208. This->numDimensions = suppInfo.textureDimension;
  209. This->baseWidth = pHeader->pixelWidth;
  210. assert(suppInfo.textureDimension > 0 && suppInfo.textureDimension < 4);
  211. switch (suppInfo.textureDimension) {
  212. case 1:
  213. This->baseHeight = This->baseDepth = 1;
  214. break;
  215. case 2:
  216. This->baseHeight = pHeader->pixelHeight;
  217. This->baseDepth = 1;
  218. break;
  219. case 3:
  220. This->baseHeight = pHeader->pixelHeight;
  221. This->baseDepth = pHeader->pixelDepth;
  222. break;
  223. }
  224. if (pHeader->numberOfArrayElements > 0) {
  225. This->numLayers = pHeader->numberOfArrayElements;
  226. This->isArray = KTX_TRUE;
  227. } else {
  228. This->numLayers = 1;
  229. This->isArray = KTX_FALSE;
  230. }
  231. This->numFaces = pHeader->numberOfFaces;
  232. if (pHeader->numberOfFaces == 6)
  233. This->isCubemap = KTX_TRUE;
  234. else
  235. This->isCubemap = KTX_FALSE;
  236. This->numLevels = pHeader->numberOfMipLevels;
  237. This->isCompressed = suppInfo.compressed;
  238. This->generateMipmaps = suppInfo.generateMipmaps;
  239. if (pHeader->endianness == KTX_ENDIAN_REF_REV)
  240. private->_needSwap = KTX_TRUE;
  241. This->_protected->_typeSize = pHeader->glTypeSize;
  242. /*
  243. * Make an empty hash list.
  244. */
  245. ktxHashList_Construct(&This->kvDataHead);
  246. /*
  247. * Load KVData.
  248. */
  249. if (pHeader->bytesOfKeyValueData > 0) {
  250. if (!(createFlags & KTX_TEXTURE_CREATE_SKIP_KVDATA_BIT)) {
  251. ktx_uint32_t kvdLen = pHeader->bytesOfKeyValueData;
  252. ktx_uint8_t* pKvd;
  253. pKvd = malloc(kvdLen);
  254. if (pKvd == NULL) {
  255. result = KTX_OUT_OF_MEMORY;
  256. goto cleanup;
  257. }
  258. result = stream->read(stream, pKvd, kvdLen);
  259. if (result != KTX_SUCCESS)
  260. goto cleanup;
  261. if (private->_needSwap) {
  262. /* Swap the counts inside the key & value data. */
  263. ktx_uint8_t* src = pKvd;
  264. ktx_uint8_t* end = pKvd + kvdLen;
  265. while (src < end) {
  266. ktx_uint32_t* pKeyAndValueByteSize = (ktx_uint32_t*)src;
  267. _ktxSwapEndian32(pKeyAndValueByteSize, 1);
  268. src += _KTX_PAD4(*pKeyAndValueByteSize);
  269. }
  270. }
  271. if (!(createFlags & KTX_TEXTURE_CREATE_RAW_KVDATA_BIT)) {
  272. char* orientation;
  273. ktx_uint32_t orientationLen;
  274. result = ktxHashList_Deserialize(&This->kvDataHead,
  275. kvdLen, pKvd);
  276. free(pKvd);
  277. if (result != KTX_SUCCESS) {
  278. goto cleanup;
  279. }
  280. result = ktxHashList_FindValue(&This->kvDataHead,
  281. KTX_ORIENTATION_KEY,
  282. &orientationLen,
  283. (void**)&orientation);
  284. assert(result != KTX_INVALID_VALUE);
  285. if (result == KTX_SUCCESS) {
  286. ktx_uint32_t count;
  287. char orient[4] = {0, 0, 0, 0};
  288. count = sscanf(orientation, KTX_ORIENTATION3_FMT,
  289. &orient[0],
  290. &orient[1],
  291. &orient[2]);
  292. if (count > This->numDimensions) {
  293. // KTX 1 is less strict than KTX2 so there is a chance
  294. // of having more dimensions than needed.
  295. count = This->numDimensions;
  296. }
  297. switch (This->numDimensions) {
  298. case 3:
  299. This->orientation.z = orient[2];
  300. FALLTHROUGH;
  301. case 2:
  302. This->orientation.y = orient[1];
  303. FALLTHROUGH;
  304. case 1:
  305. This->orientation.x = orient[0];
  306. }
  307. }
  308. } else {
  309. This->kvDataLen = kvdLen;
  310. This->kvData = pKvd;
  311. }
  312. } else {
  313. stream->skip(stream, pHeader->bytesOfKeyValueData);
  314. }
  315. }
  316. /*
  317. * Get the size of the image data.
  318. */
  319. result = stream->getsize(stream, &size);
  320. if (result != KTX_SUCCESS)
  321. goto cleanup;
  322. result = stream->getpos(stream, &pos);
  323. if (result != KTX_SUCCESS)
  324. goto cleanup;
  325. /* Remove space for faceLodSize fields */
  326. This->dataSize = size - pos - This->numLevels * sizeof(ktx_uint32_t);
  327. /*
  328. * Load the images, if requested.
  329. */
  330. if (createFlags & KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT) {
  331. result = ktxTexture1_LoadImageData(This, NULL, 0);
  332. }
  333. if (result == KTX_SUCCESS)
  334. return result;
  335. cleanup:
  336. ktxTexture1_destruct(This);
  337. return result;
  338. }
  339. /**
  340. * @memberof ktxTexture1 @private
  341. * @brief Construct a ktxTexture1 from a ktxStream reading from a KTX source.
  342. *
  343. * The stream object is copied into the constructed ktxTexture1.
  344. *
  345. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  346. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  347. * will minimize memory usage by allowing, for example, loading the images
  348. * directly from the source into a Vulkan staging buffer.
  349. *
  350. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  351. * provided solely to enable implementation of the @e libktx v1 API on top of
  352. * ktxTexture1.
  353. *
  354. * @param[in] This pointer to a ktxTexture1-sized block of memory to
  355. * initialize.
  356. * @param[in] pStream pointer to the stream to read.
  357. * @param[in] createFlags bitmask requesting specific actions during creation.
  358. *
  359. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  360. *
  361. * @exception KTX_FILE_READ_ERROR
  362. * An error occurred while reading the source.
  363. *
  364. * For other exceptions see ktxTexture1_constructFromStreamAndHeader().
  365. */
  366. static KTX_error_code
  367. ktxTexture1_constructFromStream(ktxTexture1* This, ktxStream* pStream,
  368. ktxTextureCreateFlags createFlags)
  369. {
  370. KTX_header header;
  371. KTX_error_code result;
  372. // Read header.
  373. result = pStream->read(pStream, &header, KTX_HEADER_SIZE);
  374. if (result != KTX_SUCCESS)
  375. return result;
  376. return ktxTexture1_constructFromStreamAndHeader(This, pStream,
  377. &header, createFlags);
  378. }
  379. /**
  380. * @memberof ktxTexture1 @private
  381. * @brief Construct a ktxTexture1 from a stdio stream reading from a KTX source.
  382. *
  383. * See ktxTextureInt_constructFromStream for details.
  384. *
  385. * @note Do not close the stdio stream until you are finished with the texture
  386. * object.
  387. *
  388. * @param[in] This pointer to a ktxTextureInt-sized block of memory to
  389. * initialize.
  390. * @param[in] stdioStream a stdio FILE pointer opened on the source.
  391. * @param[in] createFlags bitmask requesting specific actions during creation.
  392. *
  393. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  394. *
  395. * @exception KTX_INVALID_VALUE Either @p stdiostream or @p This is null.
  396. *
  397. * For other exceptions, see ktxTexture_constructFromStream().
  398. */
  399. static KTX_error_code
  400. ktxTexture1_constructFromStdioStream(ktxTexture1* This, FILE* stdioStream,
  401. ktxTextureCreateFlags createFlags)
  402. {
  403. ktxStream stream;
  404. KTX_error_code result;
  405. if (stdioStream == NULL || This == NULL)
  406. return KTX_INVALID_VALUE;
  407. result = ktxFileStream_construct(&stream, stdioStream, KTX_FALSE);
  408. if (result == KTX_SUCCESS)
  409. result = ktxTexture1_constructFromStream(This, &stream, createFlags);
  410. return result;
  411. }
  412. /**
  413. * @memberof ktxTexture1 @private
  414. * @brief Construct a ktxTexture1 from a named KTX file.
  415. *
  416. * See ktxTextureInt_constructFromStream for details.
  417. *
  418. * @param[in] This pointer to a ktxTextureInt-sized block of memory to
  419. * initialize.
  420. * @param[in] filename pointer to a char array containing the file name.
  421. * @param[in] createFlags bitmask requesting specific actions during creation.
  422. *
  423. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  424. *
  425. * @exception KTX_FILE_OPEN_FAILED The file could not be opened.
  426. * @exception KTX_INVALID_VALUE @p filename is @c NULL.
  427. *
  428. * For other exceptions, see ktxTexture_constructFromStream().
  429. */
  430. static KTX_error_code
  431. ktxTexture1_constructFromNamedFile(ktxTexture1* This,
  432. const char* const filename,
  433. ktxTextureCreateFlags createFlags)
  434. {
  435. FILE* file;
  436. ktxStream stream;
  437. KTX_error_code result;
  438. if (This == NULL || filename == NULL)
  439. return KTX_INVALID_VALUE;
  440. file = fopen(filename, "rb");
  441. if (!file)
  442. return KTX_FILE_OPEN_FAILED;
  443. result = ktxFileStream_construct(&stream, file, KTX_TRUE);
  444. if (result == KTX_SUCCESS)
  445. result = ktxTexture1_constructFromStream(This, &stream, createFlags);
  446. return result;
  447. }
  448. /**
  449. * @memberof ktxTexture1 @private
  450. * @brief Construct a ktxTexture1 from KTX-formatted data in memory.
  451. *
  452. * See ktxTextureInt_constructFromStream for details.
  453. *
  454. * @param[in] This pointer to a ktxTextureInt-sized block of memory to
  455. * initialize.
  456. * @param[in] bytes pointer to the memory containing the serialized KTX data.
  457. * @param[in] size length of the KTX data in bytes.
  458. * @param[in] createFlags bitmask requesting specific actions during creation.
  459. *
  460. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  461. *
  462. * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0.
  463. *
  464. * For other exceptions, see ktxTexture_constructFromStream().
  465. */
  466. static KTX_error_code
  467. ktxTexture1_constructFromMemory(ktxTexture1* This,
  468. const ktx_uint8_t* bytes, ktx_size_t size,
  469. ktxTextureCreateFlags createFlags)
  470. {
  471. ktxStream stream;
  472. KTX_error_code result;
  473. if (bytes == NULL || size == 0)
  474. return KTX_INVALID_VALUE;
  475. result = ktxMemStream_construct_ro(&stream, bytes, size);
  476. if (result == KTX_SUCCESS)
  477. result = ktxTexture1_constructFromStream(This, &stream, createFlags);
  478. return result;
  479. }
  480. void
  481. ktxTexture1_destruct(ktxTexture1* This)
  482. {
  483. if (This->_private) free(This->_private);
  484. ktxTexture_destruct(ktxTexture(This));
  485. }
  486. /**
  487. * @defgroup reader Reader
  488. * @brief Read KTX-formatted data.
  489. * @{
  490. */
  491. /**
  492. * @memberof ktxTexture1
  493. * @ingroup writer
  494. * @brief Create a new empty ktxTexture1.
  495. *
  496. * The address of the newly created ktxTexture1 is written to the location
  497. * pointed at by @p newTex.
  498. *
  499. * @param[in] createInfo pointer to a ktxTextureCreateInfo struct with
  500. * information describing the texture.
  501. * @param[in] storageAllocation
  502. * enum indicating whether or not to allocate storage
  503. * for the texture images.
  504. * @param[in,out] newTex pointer to a location in which store the address of
  505. * the newly created texture.
  506. *
  507. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  508. *
  509. * @exception KTX_INVALID_VALUE @c glInternalFormat in @p createInfo is not a
  510. * valid OpenGL internal format value.
  511. * @exception KTX_INVALID_VALUE @c numDimensions in @p createInfo is not 1, 2
  512. * or 3.
  513. * @exception KTX_INVALID_VALUE One of <tt>base{Width,Height,Depth}</tt> in
  514. * @p createInfo is 0.
  515. * @exception KTX_INVALID_VALUE @c numFaces in @p createInfo is not 1 or 6.
  516. * @exception KTX_INVALID_VALUE @c numLevels in @p createInfo is 0.
  517. * @exception KTX_INVALID_OPERATION
  518. * The <tt>base{Width,Height,Depth}</tt> specified
  519. * in @p createInfo are inconsistent with
  520. * @c numDimensions.
  521. * @exception KTX_INVALID_OPERATION
  522. * @p createInfo is requesting a 3D array or
  523. * 3D cubemap texture.
  524. * @exception KTX_INVALID_OPERATION
  525. * @p createInfo is requesting a cubemap with
  526. * non-square or non-2D images.
  527. * @exception KTX_INVALID_OPERATION
  528. * @p createInfo is requesting more mip levels
  529. * than needed for the specified
  530. * <tt>base{Width,Height,Depth}</tt>.
  531. * @exception KTX_OUT_OF_MEMORY Not enough memory for the texture's images.
  532. */
  533. KTX_error_code
  534. ktxTexture1_Create(ktxTextureCreateInfo* createInfo,
  535. ktxTextureCreateStorageEnum storageAllocation,
  536. ktxTexture1** newTex)
  537. {
  538. KTX_error_code result;
  539. if (newTex == NULL)
  540. return KTX_INVALID_VALUE;
  541. ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
  542. if (tex == NULL)
  543. return KTX_OUT_OF_MEMORY;
  544. result = ktxTexture1_construct(tex, createInfo, storageAllocation);
  545. if (result != KTX_SUCCESS) {
  546. free(tex);
  547. } else {
  548. *newTex = tex;
  549. }
  550. return result;
  551. }
  552. /**
  553. * @memberof ktxTexture1
  554. * @~English
  555. * @brief Create a ktxTexture1 from a stdio stream reading from a KTX source.
  556. *
  557. * The address of a newly created ktxTexture1 reflecting the contents of the
  558. * stdio stream is written to the location pointed at by @p newTex.
  559. *
  560. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  561. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  562. * will minimize memory usage by allowing, for example, loading the images
  563. * directly from the source into a Vulkan staging buffer.
  564. *
  565. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  566. * provided solely to enable implementation of the @e libktx v1 API on top of
  567. * ktxTexture1.
  568. *
  569. * @param[in] stdioStream stdio FILE pointer created from the desired file.
  570. * @param[in] createFlags bitmask requesting specific actions during creation.
  571. * @param[in,out] newTex pointer to a location in which store the address of
  572. * the newly created texture.
  573. *
  574. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  575. *
  576. * @exception KTX_INVALID_VALUE @p newTex is @c NULL.
  577. * @exception KTX_FILE_DATA_ERROR
  578. * Source data is inconsistent with the KTX
  579. * specification.
  580. * @exception KTX_FILE_READ_ERROR
  581. * An error occurred while reading the source.
  582. * @exception KTX_FILE_UNEXPECTED_EOF
  583. * Not enough data in the source.
  584. * @exception KTX_OUT_OF_MEMORY Not enough memory to create the texture object,
  585. * load the images or load the key-value data.
  586. * @exception KTX_UNKNOWN_FILE_FORMAT
  587. * The source is not in KTX format.
  588. * @exception KTX_UNSUPPORTED_TEXTURE_TYPE
  589. * The source describes a texture type not
  590. * supported by OpenGL or Vulkan, e.g, a 3D array.
  591. */
  592. KTX_error_code
  593. ktxTexture1_CreateFromStdioStream(FILE* stdioStream,
  594. ktxTextureCreateFlags createFlags,
  595. ktxTexture1** newTex)
  596. {
  597. KTX_error_code result;
  598. if (newTex == NULL)
  599. return KTX_INVALID_VALUE;
  600. ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
  601. if (tex == NULL)
  602. return KTX_OUT_OF_MEMORY;
  603. result = ktxTexture1_constructFromStdioStream(tex, stdioStream,
  604. createFlags);
  605. if (result == KTX_SUCCESS)
  606. *newTex = (ktxTexture1*)tex;
  607. else {
  608. free(tex);
  609. *newTex = NULL;
  610. }
  611. return result;
  612. }
  613. /*
  614. * @memberof ktxTexture1
  615. * @~English
  616. * @brief Create a ktxTexture1 from a named KTX file.
  617. *
  618. * The address of a newly created ktxTexture1 reflecting the contents of the
  619. * file is written to the location pointed at by @p newTex.
  620. *
  621. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  622. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  623. * will minimize memory usage by allowing, for example, loading the images
  624. * directly from the source into a Vulkan staging buffer.
  625. *
  626. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  627. * provided solely to enable implementation of the @e libktx v1 API on top of
  628. * ktxTexture1.
  629. *
  630. * @param[in] filename pointer to a char array containing the file name.
  631. * @param[in] createFlags bitmask requesting specific actions during creation.
  632. * @param[in,out] newTex pointer to a location in which store the address of
  633. * the newly created texture.
  634. *
  635. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  636. *
  637. * @exception KTX_FILE_OPEN_FAILED The file could not be opened.
  638. * @exception KTX_INVALID_VALUE @p filename is @c NULL.
  639. *
  640. * For other exceptions, see ktxTexture_CreateFromStdioStream().
  641. */
  642. KTX_error_code
  643. ktxTexture1_CreateFromNamedFile(const char* const filename,
  644. ktxTextureCreateFlags createFlags,
  645. ktxTexture1** newTex)
  646. {
  647. KTX_error_code result;
  648. if (newTex == NULL)
  649. return KTX_INVALID_VALUE;
  650. ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
  651. if (tex == NULL)
  652. return KTX_OUT_OF_MEMORY;
  653. result = ktxTexture1_constructFromNamedFile(tex, filename, createFlags);
  654. if (result == KTX_SUCCESS)
  655. *newTex = (ktxTexture1*)tex;
  656. else {
  657. free(tex);
  658. *newTex = NULL;
  659. }
  660. return result;
  661. }
  662. /**
  663. * @memberof ktxTexture1
  664. * @~English
  665. * @brief Create a ktxTexture1 from KTX-formatted data in memory.
  666. *
  667. * The address of a newly created ktxTexture1 reflecting the contents of the
  668. * serialized KTX data is written to the location pointed at by @p newTex.
  669. *
  670. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  671. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  672. * will minimize memory usage by allowing, for example, loading the images
  673. * directly from the source into a Vulkan staging buffer.
  674. *
  675. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  676. * provided solely to enable implementation of the @e libktx v1 API on top of
  677. * ktxTexture1.
  678. *
  679. * @param[in] bytes pointer to the memory containing the serialized KTX data.
  680. * @param[in] size length of the KTX data in bytes.
  681. * @param[in] createFlags bitmask requesting specific actions during creation.
  682. * @param[in,out] newTex pointer to a location in which store the address of
  683. * the newly created texture.
  684. *
  685. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  686. *
  687. * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0.
  688. *
  689. * For other exceptions, see ktxTexture_CreateFromStdioStream().
  690. */
  691. KTX_error_code
  692. ktxTexture1_CreateFromMemory(const ktx_uint8_t* bytes, ktx_size_t size,
  693. ktxTextureCreateFlags createFlags,
  694. ktxTexture1** newTex)
  695. {
  696. KTX_error_code result;
  697. if (newTex == NULL)
  698. return KTX_INVALID_VALUE;
  699. ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
  700. if (tex == NULL)
  701. return KTX_OUT_OF_MEMORY;
  702. result = ktxTexture1_constructFromMemory(tex, bytes, size,
  703. createFlags);
  704. if (result == KTX_SUCCESS)
  705. *newTex = (ktxTexture1*)tex;
  706. else {
  707. free(tex);
  708. *newTex = NULL;
  709. }
  710. return result;
  711. }
  712. /**
  713. * @memberof ktxTexture1
  714. * @~English
  715. * @brief Create a ktxTexture1 from KTX-formatted data from a `ktxStream`.
  716. *
  717. * The address of a newly created ktxTexture1 reflecting the contents of the
  718. * serialized KTX data is written to the location pointed at by @p newTex.
  719. *
  720. * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
  721. * if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
  722. * will minimize memory usage by allowing, for example, loading the images
  723. * directly from the source into a Vulkan staging buffer.
  724. *
  725. * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
  726. * provided solely to enable implementation of the @e libktx v1 API on top of
  727. * ktxTexture1.
  728. *
  729. * @param[in] stream pointer to the stream to read KTX data from.
  730. * @param[in] createFlags bitmask requesting specific actions during creation.
  731. * @param[in,out] newTex pointer to a location in which store the address of
  732. * the newly created texture.
  733. *
  734. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  735. *
  736. * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0.
  737. *
  738. * For other exceptions, see ktxTexture_CreateFromStdioStream().
  739. */
  740. KTX_error_code
  741. ktxTexture1_CreateFromStream(ktxStream* stream,
  742. ktxTextureCreateFlags createFlags,
  743. ktxTexture1** newTex)
  744. {
  745. KTX_error_code result;
  746. if (newTex == NULL)
  747. return KTX_INVALID_VALUE;
  748. ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
  749. if (tex == NULL)
  750. return KTX_OUT_OF_MEMORY;
  751. result = ktxTexture1_constructFromStream(tex, stream, createFlags);
  752. if (result == KTX_SUCCESS)
  753. *newTex = (ktxTexture1*)tex;
  754. else {
  755. free(tex);
  756. *newTex = NULL;
  757. }
  758. return result;
  759. }
  760. /**
  761. * @memberof ktxTexture1
  762. * @~English
  763. * @brief Destroy a ktxTexture1 object.
  764. *
  765. * This frees the memory associated with the texture contents and the memory
  766. * of the ktxTexture1 object. This does @e not delete any OpenGL or Vulkan
  767. * texture objects created by ktxTexture1_GLUpload or ktxTexture1_VkUpload.
  768. *
  769. * @param[in] This pointer to the ktxTexture1 object to destroy
  770. */
  771. void
  772. ktxTexture1_Destroy(ktxTexture1* This)
  773. {
  774. ktxTexture1_destruct(This);
  775. free(This);
  776. }
  777. /**
  778. * @memberof ktxTexture @private
  779. * @~English
  780. * @brief Calculate the size of the image data for the specified number
  781. * of levels.
  782. *
  783. * The data size is the sum of the sizes of each level up to the number
  784. * specified and includes any @c mipPadding.
  785. *
  786. * @param[in] This pointer to the ktxTexture object of interest.
  787. * @param[in] levels number of levels whose data size to return.
  788. *
  789. * @return the data size in bytes.
  790. */
  791. ktx_size_t
  792. ktxTexture1_calcDataSizeLevels(ktxTexture1* This, ktx_uint32_t levels)
  793. {
  794. ktx_uint32_t i;
  795. ktx_size_t dataSize = 0;
  796. assert(This != NULL);
  797. assert(levels <= This->numLevels);
  798. for (i = 0; i < levels; i++) {
  799. ktx_size_t levelSize = ktxTexture_calcLevelSize(ktxTexture(This), i,
  800. KTX_FORMAT_VERSION_ONE);
  801. /* mipPadding. NOTE: this adds padding after the last level too. */
  802. #if KTX_GL_UNPACK_ALIGNMENT != 4
  803. dataSize += _KTX_PAD4(levelSize);
  804. #else
  805. dataSize += levelSize;
  806. #endif
  807. }
  808. return dataSize;
  809. }
  810. /**
  811. * @memberof ktxTexture1 @private
  812. * @~English
  813. *
  814. * @copydoc ktxTexture::ktxTexture_doCalcFaceLodSize
  815. */
  816. ktx_size_t
  817. ktxTexture1_calcFaceLodSize(ktxTexture1* This, ktx_uint32_t level)
  818. {
  819. return ktxTexture_doCalcFaceLodSize(ktxTexture(This), level,
  820. KTX_FORMAT_VERSION_ONE);
  821. }
  822. /**
  823. * @memberof ktxTexture @private
  824. * @~English
  825. * @brief Return the offset of a level in bytes from the start of the image
  826. * data in a ktxTexture.
  827. *
  828. * The caclulated size does not include space for storing the @c imageSize
  829. * fields of each mip level.
  830. *
  831. * @param[in] This pointer to the ktxTexture object of interest.
  832. * @param[in] level level whose offset to return.
  833. * @param[in] fv enum specifying format version for which to calculate
  834. * image size.
  835. *
  836. * @return the data size in bytes.
  837. */
  838. ktx_size_t
  839. ktxTexture1_calcLevelOffset(ktxTexture1* This, ktx_uint32_t level)
  840. {
  841. assert (This != NULL);
  842. assert (level < This->numLevels);
  843. return ktxTexture1_calcDataSizeLevels(This, level);
  844. }
  845. /**
  846. * @memberof ktxTexture1
  847. * @~English
  848. * @brief Find the offset of an image within a ktxTexture's image data.
  849. *
  850. * As there is no such thing as a 3D cubemap we make the 3rd location parameter
  851. * do double duty.
  852. *
  853. * @param[in] This pointer to the ktxTexture object of interest.
  854. * @param[in] level mip level of the image.
  855. * @param[in] layer array layer of the image.
  856. * @param[in] faceSlice cube map face or depth slice of the image.
  857. * @param[in,out] pOffset pointer to location to store the offset.
  858. *
  859. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  860. *
  861. * @exception KTX_INVALID_OPERATION
  862. * @p level, @p layer or @p faceSlice exceed the
  863. * dimensions of the texture.
  864. * @exception KTX_INVALID_VALID @p This is NULL.
  865. */
  866. KTX_error_code
  867. ktxTexture1_GetImageOffset(ktxTexture1* This, ktx_uint32_t level,
  868. ktx_uint32_t layer, ktx_uint32_t faceSlice,
  869. ktx_size_t* pOffset)
  870. {
  871. if (This == NULL)
  872. return KTX_INVALID_VALUE;
  873. if (level >= This->numLevels || layer >= This->numLayers)
  874. return KTX_INVALID_OPERATION;
  875. if (This->isCubemap) {
  876. if (faceSlice >= This->numFaces)
  877. return KTX_INVALID_OPERATION;
  878. } else {
  879. ktx_uint32_t maxSlice = MAX(1, This->baseDepth >> level);
  880. if (faceSlice >= maxSlice)
  881. return KTX_INVALID_OPERATION;
  882. }
  883. // Get the size of the data up to the start of the indexed level.
  884. *pOffset = ktxTexture_calcDataSizeLevels(ktxTexture(This), level);
  885. // All layers, faces & slices within a level are the same size.
  886. if (layer != 0) {
  887. ktx_size_t layerSize;
  888. layerSize = ktxTexture_layerSize(ktxTexture(This), level,
  889. KTX_FORMAT_VERSION_ONE);
  890. *pOffset += layer * layerSize;
  891. }
  892. if (faceSlice != 0) {
  893. ktx_size_t imageSize;
  894. imageSize = ktxTexture_GetImageSize(ktxTexture(This), level);
  895. #if (KTX_GL_UNPACK_ALIGNMENT != 4)
  896. if (This->isCubemap)
  897. _KTX_PAD4(imageSize); // Account for cubePadding.
  898. #endif
  899. *pOffset += faceSlice * imageSize;
  900. }
  901. return KTX_SUCCESS;
  902. }
  903. /**
  904. * @memberof ktxTexture1
  905. * @~English
  906. * @brief Return the total size in bytes of the uncompressed data of a ktxTexture1.
  907. *
  908. * This always returns the value of @c This->dataSize. The function is provided for
  909. * symmetry with ktxTexture2.
  910. *
  911. * @param[in] This pointer to the ktxTexture1 object of interest.
  912. * @return The size of the data in the texture.
  913. */
  914. ktx_size_t
  915. ktxTexture1_GetDataSizeUncompressed(ktxTexture1* This)
  916. {
  917. return This->dataSize;
  918. }
  919. /**
  920. * @memberof ktxTexture1
  921. * @~English
  922. * @brief Calculate & return the size in bytes of an image at the specified
  923. * mip level.
  924. *
  925. * For arrays, this is the size of layer, for cubemaps, the size of a face
  926. * and for 3D textures, the size of a depth slice.
  927. *
  928. * The size reflects the padding of each row to KTX_GL_UNPACK_ALIGNMENT.
  929. *
  930. * @param[in] This pointer to the ktxTexture1 object of interest.
  931. * @param[in] level level of interest.
  932. */
  933. ktx_size_t
  934. ktxTexture1_GetImageSize(ktxTexture1* This, ktx_uint32_t level)
  935. {
  936. return ktxTexture_calcImageSize(ktxTexture(This), level,
  937. KTX_FORMAT_VERSION_ONE);
  938. }
  939. /**
  940. * @memberof ktxTexture1 @private
  941. * @~English
  942. * @brief Return the size of the primitive type of a single color component
  943. *
  944. * @param[in] This pointer to the ktxTexture1 object of interest.
  945. *
  946. * @return the type size in bytes.
  947. */
  948. ktx_uint32_t
  949. ktxTexture1_glTypeSize(ktxTexture1* This)
  950. {
  951. assert(This != NULL);
  952. return This->_protected->_typeSize;
  953. }
  954. /**
  955. * @memberof ktxTexture1
  956. * @~English
  957. * @brief Iterate over the mip levels in a ktxTexture1 object.
  958. *
  959. * This is almost identical to ktxTexture_IterateLevelFaces(). The difference is
  960. * that the blocks of image data for non-array cube maps include all faces of
  961. * a mip level.
  962. *
  963. * This function works even if @p This->pData == 0 so it can be used to
  964. * obtain offsets and sizes for each level by callers who have loaded the data
  965. * externally.
  966. *
  967. * @param[in] This handle of the 1 opened on the data.
  968. * @param[in,out] iterCb the address of a callback function which is called
  969. * with the data for each image block.
  970. * @param[in,out] userdata the address of application-specific data which is
  971. * passed to the callback along with the image data.
  972. *
  973. * @return KTX_SUCCESS on success, other KTX_* enum values on error. The
  974. * following are returned directly by this function. @p iterCb may
  975. * return these for other causes or may return additional errors.
  976. *
  977. * @exception KTX_FILE_DATA_ERROR Mip level sizes are increasing not
  978. * decreasing
  979. * @exception KTX_INVALID_VALUE @p This is @c NULL or @p iterCb is @c NULL.
  980. *
  981. */
  982. KTX_error_code
  983. ktxTexture1_IterateLevels(ktxTexture1* This, PFNKTXITERCB iterCb, void* userdata)
  984. {
  985. ktx_uint32_t miplevel;
  986. KTX_error_code result = KTX_SUCCESS;
  987. if (This == NULL)
  988. return KTX_INVALID_VALUE;
  989. if (iterCb == NULL)
  990. return KTX_INVALID_VALUE;
  991. for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
  992. {
  993. GLsizei width, height, depth;
  994. ktx_uint32_t levelSize;
  995. ktx_size_t offset;
  996. /* Array textures have the same number of layers at each mip level. */
  997. width = MAX(1, This->baseWidth >> miplevel);
  998. height = MAX(1, This->baseHeight >> miplevel);
  999. depth = MAX(1, This->baseDepth >> miplevel);
  1000. levelSize = (ktx_uint32_t)ktxTexture_calcLevelSize(ktxTexture(This),
  1001. miplevel,
  1002. KTX_FORMAT_VERSION_ONE);
  1003. /* All array layers are passed in a group because that is how
  1004. * GL & Vulkan need them. Hence no
  1005. * for (layer = 0; layer < This->numLayers)
  1006. */
  1007. ktxTexture_GetImageOffset(ktxTexture(This), miplevel, 0, 0, &offset);
  1008. result = iterCb(miplevel, 0, width, height, depth,
  1009. levelSize, This->pData + offset, userdata);
  1010. if (result != KTX_SUCCESS)
  1011. break;
  1012. }
  1013. return result;
  1014. }
  1015. /**
  1016. * @memberof ktxTexture1
  1017. * @~English
  1018. * @brief Iterate over the images in a ktxTexture1 object while loading the
  1019. * image data.
  1020. *
  1021. * This operates similarly to ktxTexture_IterateLevelFaces() except that it
  1022. * loads the images from the ktxTexture1's source to a temporary buffer
  1023. * while iterating. The callback function must copy the image data if it
  1024. * wishes to preserve it as the temporary buffer is reused for each level and
  1025. * is freed when this function exits.
  1026. *
  1027. * This function is helpful for reducing memory usage when uploading the data
  1028. * to a graphics API.
  1029. *
  1030. * @param[in] This pointer to the ktxTexture1 object of interest.
  1031. * @param[in,out] iterCb the address of a callback function which is called
  1032. * with the data for each image.
  1033. * @param[in,out] userdata the address of application-specific data which is
  1034. * passed to the callback along with the image data.
  1035. *
  1036. * @return KTX_SUCCESS on success, other KTX_* enum values on error. The
  1037. * following are returned directly by this function. @p iterCb may
  1038. * return these for other causes or may return additional errors.
  1039. *
  1040. * @exception KTX_FILE_DATA_ERROR mip level sizes are increasing not
  1041. * decreasing
  1042. * @exception KTX_INVALID_OPERATION the ktxTexture1 was not created from a
  1043. * stream, i.e there is no data to load, or
  1044. * this ktxTexture1's images have already
  1045. * been loaded.
  1046. * @exception KTX_INVALID_VALUE @p This is @c NULL or @p iterCb is @c NULL.
  1047. * @exception KTX_OUT_OF_MEMORY not enough memory to allocate a block to
  1048. * hold the base level image.
  1049. */
  1050. KTX_error_code
  1051. ktxTexture1_IterateLoadLevelFaces(ktxTexture1* This, PFNKTXITERCB iterCb,
  1052. void* userdata)
  1053. {
  1054. DECLARE_PRIVATE(ktxTexture1);
  1055. struct ktxTexture_protected* prtctd = This->_protected;
  1056. ktxStream* stream = (ktxStream *)&prtctd->_stream;
  1057. ktx_uint32_t dataSize = 0;
  1058. ktx_uint32_t miplevel;
  1059. KTX_error_code result = KTX_SUCCESS;
  1060. void* data = NULL;
  1061. if (This == NULL)
  1062. return KTX_INVALID_VALUE;
  1063. if (This->classId != ktxTexture1_c)
  1064. return KTX_INVALID_OPERATION;
  1065. if (iterCb == NULL)
  1066. return KTX_INVALID_VALUE;
  1067. if (prtctd->_stream.data.file == NULL)
  1068. // This Texture not created from a stream or images are already loaded.
  1069. return KTX_INVALID_OPERATION;
  1070. for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
  1071. {
  1072. ktx_uint32_t faceLodSize;
  1073. ktx_uint32_t faceLodSizePadded;
  1074. ktx_uint32_t face;
  1075. ktx_uint32_t innerIterations;
  1076. GLsizei width, height, depth;
  1077. /* Array textures have the same number of layers at each mip level. */
  1078. width = MAX(1, This->baseWidth >> miplevel);
  1079. height = MAX(1, This->baseHeight >> miplevel);
  1080. depth = MAX(1, This->baseDepth >> miplevel);
  1081. result = stream->read(stream, &faceLodSize, sizeof(ktx_uint32_t));
  1082. if (result != KTX_SUCCESS) {
  1083. goto cleanup;
  1084. }
  1085. if (private->_needSwap) {
  1086. _ktxSwapEndian32(&faceLodSize, 1);
  1087. }
  1088. #if (KTX_GL_UNPACK_ALIGNMENT != 4)
  1089. faceLodSizePadded = _KTX_PAD4(faceLodSize);
  1090. #else
  1091. faceLodSizePadded = faceLodSize;
  1092. #endif
  1093. if (!data) {
  1094. /* allocate memory sufficient for the base miplevel */
  1095. data = malloc(faceLodSizePadded);
  1096. if (!data) {
  1097. result = KTX_OUT_OF_MEMORY;
  1098. goto cleanup;
  1099. }
  1100. dataSize = faceLodSizePadded;
  1101. }
  1102. else if (dataSize < faceLodSizePadded) {
  1103. /* subsequent miplevels cannot be larger than the base miplevel */
  1104. result = KTX_FILE_DATA_ERROR;
  1105. goto cleanup;
  1106. }
  1107. /* All array layers are passed in a group because that is how
  1108. * GL & Vulkan need them. Hence no
  1109. * for (layer = 0; layer < This->numLayers)
  1110. */
  1111. if (This->isCubemap && !This->isArray)
  1112. innerIterations = This->numFaces;
  1113. else
  1114. innerIterations = 1;
  1115. for (face = 0; face < innerIterations; ++face)
  1116. {
  1117. /* And all z_slices are also passed as a group hence no
  1118. * for (z_slice = 0; z_slice < This->depth)
  1119. */
  1120. result = stream->read(stream, data, faceLodSizePadded);
  1121. if (result != KTX_SUCCESS) {
  1122. goto cleanup;
  1123. }
  1124. /* Perform endianness conversion on texture data */
  1125. if (private->_needSwap) {
  1126. if (prtctd->_typeSize == 2)
  1127. _ktxSwapEndian16((ktx_uint16_t*)data, faceLodSize / 2);
  1128. else if (prtctd->_typeSize == 4)
  1129. _ktxSwapEndian32((ktx_uint32_t*)data, faceLodSize / 4);
  1130. }
  1131. result = iterCb(miplevel, face,
  1132. width, height, depth,
  1133. faceLodSize, data, userdata);
  1134. }
  1135. }
  1136. cleanup:
  1137. free(data);
  1138. // No further need for this.
  1139. stream->destruct(stream);
  1140. return result;
  1141. }
  1142. /**
  1143. * @memberof ktxTexture1
  1144. * @~English
  1145. * @brief Load all the image data from the ktxTexture1's source.
  1146. *
  1147. * The data is loaded into the provided buffer or to an internally allocated
  1148. * buffer, if @p pBuffer is @c NULL.
  1149. *
  1150. * @param[in] This pointer to the ktxTexture object of interest.
  1151. * @param[in] pBuffer pointer to the buffer in which to load the image data.
  1152. * @param[in] bufSize size of the buffer pointed at by @p pBuffer.
  1153. *
  1154. * @return KTX_SUCCESS on success, other KTX_* enum values on error.
  1155. *
  1156. * @exception KTX_INVALID_VALUE @p This is NULL.
  1157. * @exception KTX_INVALID_VALUE @p bufSize is less than the the image data size.
  1158. * @exception KTX_INVALID_OPERATION
  1159. * The data has already been loaded or the
  1160. * ktxTexture was not created from a KTX source.
  1161. * @exception KTX_OUT_OF_MEMORY Insufficient memory for the image data.
  1162. */
  1163. KTX_error_code
  1164. ktxTexture1_LoadImageData(ktxTexture1* This,
  1165. ktx_uint8_t* pBuffer, ktx_size_t bufSize)
  1166. {
  1167. DECLARE_PROTECTED(ktxTexture);
  1168. DECLARE_PRIVATE(ktxTexture1);
  1169. ktx_uint32_t miplevel;
  1170. ktx_uint8_t* pDest;
  1171. KTX_error_code result = KTX_SUCCESS;
  1172. if (This == NULL)
  1173. return KTX_INVALID_VALUE;
  1174. if (prtctd->_stream.data.file == NULL)
  1175. // This Texture not created from a stream or images already loaded;
  1176. return KTX_INVALID_OPERATION;
  1177. if (pBuffer == NULL) {
  1178. This->pData = malloc(This->dataSize);
  1179. if (This->pData == NULL)
  1180. return KTX_OUT_OF_MEMORY;
  1181. pDest = This->pData;
  1182. } else if (bufSize < This->dataSize) {
  1183. return KTX_INVALID_VALUE;
  1184. } else {
  1185. pDest = pBuffer;
  1186. }
  1187. // Need to loop through for correct byte swapping
  1188. for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
  1189. {
  1190. ktx_uint32_t faceLodSize;
  1191. ktx_uint32_t faceLodSizePadded;
  1192. ktx_uint32_t face;
  1193. ktx_uint32_t innerIterations;
  1194. result = prtctd->_stream.read(&prtctd->_stream, &faceLodSize,
  1195. sizeof(ktx_uint32_t));
  1196. if (result != KTX_SUCCESS) {
  1197. goto cleanup;
  1198. }
  1199. if (private->_needSwap) {
  1200. _ktxSwapEndian32(&faceLodSize, 1);
  1201. }
  1202. #if (KTX_GL_UNPACK_ALIGNMENT != 4)
  1203. faceLodSizePadded = _KTX_PAD4(faceLodSize);
  1204. #else
  1205. faceLodSizePadded = faceLodSize;
  1206. #endif
  1207. if (This->isCubemap && !This->isArray)
  1208. innerIterations = This->numFaces;
  1209. else
  1210. innerIterations = 1;
  1211. for (face = 0; face < innerIterations; ++face)
  1212. {
  1213. result = prtctd->_stream.read(&prtctd->_stream, pDest,
  1214. faceLodSizePadded);
  1215. if (result != KTX_SUCCESS) {
  1216. goto cleanup;
  1217. }
  1218. /* Perform endianness conversion on texture data */
  1219. if (private->_needSwap) {
  1220. if (prtctd->_typeSize == 2)
  1221. _ktxSwapEndian16((ktx_uint16_t*)pDest, faceLodSize / 2);
  1222. else if (prtctd->_typeSize == 4)
  1223. _ktxSwapEndian32((ktx_uint32_t*)pDest, faceLodSize / 4);
  1224. }
  1225. pDest += faceLodSizePadded;
  1226. }
  1227. }
  1228. cleanup:
  1229. // No further need for This->
  1230. prtctd->_stream.destruct(&prtctd->_stream);
  1231. return result;
  1232. }
  1233. ktx_bool_t
  1234. ktxTexture1_NeedsTranscoding(ktxTexture1* This)
  1235. {
  1236. UNUSED(This);
  1237. return KTX_FALSE;
  1238. }
  1239. #if !KTX_FEATURE_WRITE
  1240. /*
  1241. * Stubs for writer functions that return a proper error code
  1242. */
  1243. KTX_error_code
  1244. ktxTexture1_SetImageFromMemory(ktxTexture1* This, ktx_uint32_t level,
  1245. ktx_uint32_t layer, ktx_uint32_t faceSlice,
  1246. const ktx_uint8_t* src, ktx_size_t srcSize)
  1247. {
  1248. UNUSED(This);
  1249. UNUSED(level);
  1250. UNUSED(layer);
  1251. UNUSED(faceSlice);
  1252. UNUSED(src);
  1253. UNUSED(srcSize);
  1254. return KTX_INVALID_OPERATION;
  1255. }
  1256. KTX_error_code
  1257. ktxTexture1_SetImageFromStdioStream(ktxTexture1* This, ktx_uint32_t level,
  1258. ktx_uint32_t layer, ktx_uint32_t faceSlice,
  1259. FILE* src, ktx_size_t srcSize)
  1260. {
  1261. UNUSED(This);
  1262. UNUSED(level);
  1263. UNUSED(layer);
  1264. UNUSED(faceSlice);
  1265. UNUSED(src);
  1266. UNUSED(srcSize);
  1267. return KTX_INVALID_OPERATION;
  1268. }
  1269. KTX_error_code
  1270. ktxTexture1_WriteToStdioStream(ktxTexture1* This, FILE* dstsstr)
  1271. {
  1272. UNUSED(This);
  1273. UNUSED(dstsstr);
  1274. return KTX_INVALID_OPERATION;
  1275. }
  1276. KTX_error_code
  1277. ktxTexture1_WriteToNamedFile(ktxTexture1* This, const char* const dstname)
  1278. {
  1279. UNUSED(This);
  1280. UNUSED(dstname);
  1281. return KTX_INVALID_OPERATION;
  1282. }
  1283. KTX_error_code
  1284. ktxTexture1_WriteToMemory(ktxTexture1* This,
  1285. ktx_uint8_t** ppDstBytes, ktx_size_t* pSize)
  1286. {
  1287. UNUSED(This);
  1288. UNUSED(ppDstBytes);
  1289. UNUSED(pSize);
  1290. return KTX_INVALID_OPERATION;
  1291. }
  1292. KTX_error_code
  1293. ktxTexture1_WriteToStream(ktxTexture1* This,
  1294. ktxStream* dststr)
  1295. {
  1296. UNUSED(This);
  1297. UNUSED(dststr);
  1298. return KTX_INVALID_OPERATION;
  1299. }
  1300. #endif
  1301. /*
  1302. * Initialized here at the end to avoid the need for multiple declarations of
  1303. * these functions.
  1304. */
  1305. struct ktxTexture_vtblInt ktxTexture1_vtblInt = {
  1306. (PFNCALCDATASIZELEVELS)ktxTexture1_calcDataSizeLevels,
  1307. (PFNCALCFACELODSIZE)ktxTexture1_calcFaceLodSize,
  1308. (PFNCALCLEVELOFFSET)ktxTexture1_calcLevelOffset
  1309. };
  1310. struct ktxTexture_vtbl ktxTexture1_vtbl = {
  1311. (PFNKTEXDESTROY)ktxTexture1_Destroy,
  1312. (PFNKTEXGETIMAGEOFFSET)ktxTexture1_GetImageOffset,
  1313. (PFNKTEXGETDATASIZEUNCOMPRESSED)ktxTexture1_GetDataSizeUncompressed,
  1314. (PFNKTEXGETIMAGESIZE)ktxTexture1_GetImageSize,
  1315. (PFNKTEXITERATELEVELS)ktxTexture1_IterateLevels,
  1316. (PFNKTEXITERATELOADLEVELFACES)ktxTexture1_IterateLoadLevelFaces,
  1317. (PFNKTEXNEEDSTRANSCODING)ktxTexture1_NeedsTranscoding,
  1318. (PFNKTEXLOADIMAGEDATA)ktxTexture1_LoadImageData,
  1319. (PFNKTEXSETIMAGEFROMMEMORY)ktxTexture1_SetImageFromMemory,
  1320. (PFNKTEXSETIMAGEFROMSTDIOSTREAM)ktxTexture1_SetImageFromStdioStream,
  1321. (PFNKTEXWRITETOSTDIOSTREAM)ktxTexture1_WriteToStdioStream,
  1322. (PFNKTEXWRITETONAMEDFILE)ktxTexture1_WriteToNamedFile,
  1323. (PFNKTEXWRITETOMEMORY)ktxTexture1_WriteToMemory,
  1324. (PFNKTEXWRITETOSTREAM)ktxTexture1_WriteToStream,
  1325. };
  1326. /** @} */