* @memberof ktxTexture2 @private * @ingroup reader * @~English * @brief Transcode a KTX2 texture with BasisLZ supercompressed ETC1S images. * * Inflates the images from BasisLZ supercompression back to ETC1S * then transcodes them to the specified block-compressed format. The * transcoded images replace the original images and the texture's fields * including the DFD are modified to reflec
| 454 | * @exception KTX_OUT_OF_MEMORY Not enough memory to carry out transcoding. |
| 455 | */ |
| 456 | KTX_error_code |
| 457 | ktxTexture2_transcodeLzEtc1s(ktxTexture2* This, |
| 458 | alpha_content_e alphaContent, |
| 459 | ktxTexture2* prototype, |
| 460 | ktx_transcode_fmt_e outputFormat, |
| 461 | ktx_transcode_flags transcodeFlags) |
| 462 | { |
| 463 | DECLARE_PRIVATE(priv, This); |
| 464 | DECLARE_PRIVATE(protoPriv, prototype); |
| 465 | KTX_error_code result = KTX_SUCCESS; |
| 466 | |
| 467 | assert(This->supercompressionScheme == KTX_SS_BASIS_LZ); |
| 468 | |
| 469 | uint8_t* bgd = priv._supercompressionGlobalData; |
| 470 | ktxBasisLzGlobalHeader& bgdh = *reinterpret_cast<ktxBasisLzGlobalHeader*>(bgd); |
| 471 | if (!(bgdh.endpointsByteLength && bgdh.selectorsByteLength && bgdh.tablesByteLength)) { |
| 472 | debug_printf("ktxTexture_TranscodeBasis: missing endpoints, selectors or tables"); |
| 473 | return KTX_FILE_DATA_ERROR; |
| 474 | } |
| 475 | |
| 476 | // Compute some helpful numbers. |
| 477 | // |
| 478 | // firstImages contains the indices of the first images for each level to |
| 479 | // ease finding the correct slice description when iterating from smallest |
| 480 | // level to largest or when randomly accessing them (t.b.c). The last array |
| 481 | // entry contains the total number of images, for calculating the offsets |
| 482 | // of the endpoints, etc. |
| 483 | uint32_t* firstImages = new uint32_t[This->numLevels+1]; |
| 484 | |
| 485 | // Temporary invariant value |
| 486 | uint32_t layersFaces = This->numLayers * This->numFaces; |
| 487 | firstImages[0] = 0; |
| 488 | for (uint32_t level = 1; level <= This->numLevels; level++) { |
| 489 | // NOTA BENE: numFaces * depth is only reasonable because they can't |
| 490 | // both be > 1. I.e there are no 3d cubemaps. |
| 491 | firstImages[level] = firstImages[level - 1] |
| 492 | + layersFaces * MAX(This->baseDepth >> (level - 1), 1); |
| 493 | } |
| 494 | uint32_t& imageCount = firstImages[This->numLevels]; |
| 495 | |
| 496 | if (BGD_TABLES_ADDR(0, bgdh, imageCount) + bgdh.tablesByteLength > priv._sgdByteLength) { |
| 497 | // Compiler will not allow `goto cleanup;` because "jump bypasses variable initialization." |
| 498 | // The static initializations below this and before the loop are presumably the issue |
| 499 | // as the compiler is,presumably, inserting code to destruct those at the end of the |
| 500 | // function. |
| 501 | delete[] firstImages; |
| 502 | return KTX_FILE_DATA_ERROR; |
| 503 | } |
| 504 | // FIXME: Do more validation. |
| 505 | |
| 506 | // Prepare low-level transcoder for transcoding slices. |
| 507 | basist::basisu_lowlevel_etc1s_transcoder bit; |
| 508 | |
| 509 | // basisu_transcoder_state is used to find the previous frame when |
| 510 | // decoding a video P-Frame. It tracks the previous frame for each mip |
| 511 | // level. For cube map array textures we need to find the previous frame |
| 512 | // for each face so we a state per face. Although providing this is only |
| 513 | // needed for video, it is easier to always pass our own. |
no test coverage detected