diff --git a/contrib/single_file_transcoder/README.md b/contrib/single_file_transcoder/README.md index dffa10f..8f7e1a8 100644 --- a/contrib/single_file_transcoder/README.md +++ b/contrib/single_file_transcoder/README.md @@ -9,11 +9,17 @@ cd basis_universal/contrib/single_file_transcoder ``` Then add the resulting file to your project (see the [example files](examples)). -`create_translib.sh` will run the above script, creating the file `basisutranslib.cpp`. +If certain features will _never__ be enabled, e.g. `BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY`, then `combine.sh` can be told to exclude files completely: +``` +./combine.sh -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -o basisutranslib.cpp basisutranslib-in.cpp +``` +Excluding the BC7 mode 6 support reduces the generated source by 1.2MB, which is the choice taken in both `basisutranslib-in.cpp` and `create_translib.sh`, will run the above script, creating the final `basisutranslib.cpp`. + +Note: the amalgamation script will run on pretty much anything but is _extremely_ slow on Windows with the `bash` included with Git. Why? ---- Because all it now takes to support Basis Universal is the addition of a single file, two if using the header, with no configuration or further build steps (the out-of-the-box defaults tailor the included formats for various platforms). -The library is small, adding, for example, 249kB to an Emscripten compiled WebAssembly project (with transcoding disabled for BC7 and ATC; disabling ASTC can remove a further 64kB, and `gzip` will approximately half the `wasm` file). +The library is small, adding, for example, 249kB to an Emscripten compiled WebAssembly project (with transcoding disabled for BC7 and ATC; disabling ASTC will remove a further 64kB, and `gzip` will approximately half the `wasm` file). diff --git a/contrib/single_file_transcoder/basisutranslib-in.cpp b/contrib/single_file_transcoder/basisutranslib-in.cpp index 09018eb..783df8c 100644 --- a/contrib/single_file_transcoder/basisutranslib-in.cpp +++ b/contrib/single_file_transcoder/basisutranslib-in.cpp @@ -1,8 +1,11 @@ /** * Basis Universal single file library. Generated using: * \code - * ./combine.sh -r ../../transcoder -o basisutranslib.cpp basisutranslib-in.cpp + * ./combine.sh -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -o basisutranslib.cpp basisutranslib-in.cpp * \endcode + * + * \note The script above excludes the BC7 mode 6 tables, a choice reflected in + * the build options. */ /* diff --git a/contrib/single_file_transcoder/combine.sh b/contrib/single_file_transcoder/combine.sh index ccf11cc..52ea071 100755 --- a/contrib/single_file_transcoder/combine.sh +++ b/contrib/single_file_transcoder/combine.sh @@ -20,8 +20,9 @@ DESTN="" # Prints the script usage then exits usage() { - echo "Usage: $0 [-r ] [-o ] infile" + echo "Usage: $0 [-r ] [-x
][-o ] infile" echo " -r file root search paths" + echo " -x file to exclude from inlining" echo " -o output file (otherwise stdout)" echo "Example: $0 -r ../my/path - r ../other/path -o out.c in.c" exit 1 @@ -94,11 +95,14 @@ add_file() { fi } -while getopts ":r:o:" opts; do +while getopts ":r:x:o:" opts; do case $opts in r) ROOTS="$OPTARG $ROOTS" ;; + x) + FOUND="$OPTARG $FOUND" + ;; o) DESTN="$OPTARG" ;; diff --git a/contrib/single_file_transcoder/create_translib.sh b/contrib/single_file_transcoder/create_translib.sh index 8033017..f20daf3 100755 --- a/contrib/single_file_transcoder/create_translib.sh +++ b/contrib/single_file_transcoder/create_translib.sh @@ -1,7 +1,8 @@ #!/bin/sh echo "Amalgamating files... this can take a while" -./combine.sh -r "../../transcoder" -o basisutranslib.cpp basisutranslib-in.cpp +echo "Note: basisu_transcoder_tables_bc7_m6.inc is excluded" +./combine.sh -r "../../transcoder" -x basisu_transcoder_tables_bc7_m6.inc -o basisutranslib.cpp basisutranslib-in.cpp # Did combining work? if [ $? -ne 0 ]; then echo "Combine script: FAILED" diff --git a/contrib/single_file_transcoder/examples/emscripten.cpp b/contrib/single_file_transcoder/examples/emscripten.cpp index 8afa343..c04dd3a 100644 --- a/contrib/single_file_transcoder/examples/emscripten.cpp +++ b/contrib/single_file_transcoder/examples/emscripten.cpp @@ -1,7 +1,7 @@ /** * \file emscripten.cpp * Emscripten example of using the single-file \c basisutranslib. Draws a - * rotating textured quad with data from the in-line compressed texture. + * rotating textured quad with data from the in-line compressed textures. * \n * Compile using: * \code @@ -18,10 +18,7 @@ * basisutranslib.cpp include (which stubs the texture creation). * \n * Example code released under a CC0 license. - * - * \todo add mipmap support to the example */ - #include #include #include @@ -1961,7 +1958,7 @@ struct posTex2d { #define COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 #endif -//***************************** Basis Universal /*****************************/ +//***************************** Basis Universal ******************************/ /* * All of the BasisU code is within this block to enable building with or @@ -2003,11 +2000,11 @@ static transcoder_texture_format supports(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE const #if BASISD_SUPPORT_ASTC || !defined(BASISD_SUPPORT_ASTC) /* * Then Android, ChromeOS and others with ASTC (newer iOS devices should - * make the list but don't appear to be exposed). + * make the list but don't appear to be exposed from WebGL). */ static bool const astc = GL_HAS_EXT(ctx, "WEBGL_compressed_texture_astc"); if (astc) { - //return cTFASTC_4x4; // 10 + return cTFASTC_4x4; // 10 } #endif #if BASISD_SUPPORT_DXT1 || !defined(BASISD_SUPPORT_DXT1) @@ -2092,43 +2089,60 @@ static GLenum toGlType(transcoder_texture_format const type) { * \param[in] data \c .basis file content * \param[in] size number of bytes in \a data * \return \c true if the texture was decoded and created + * + * \todo reuse the decode buffer (the first mips level should be able to contain the rest) */ bool upload(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE const ctx, GLuint const name, const uint8_t* const data, size_t const size) { - bool success = false; basisu_transcoder_init(); if (!globalCodebook) { globalCodebook = new etc1_global_selector_codebook(g_global_selector_cb_size, g_global_selector_cb); } basisu_transcoder transcoder(globalCodebook); + bool success = false; if (transcoder.validate_header(data, size)) { + glBindTexture(GL_TEXTURE_2D, name); basisu_file_info fileInfo; if (transcoder.get_file_info(data, size, fileInfo)) { transcoder_texture_format type = supports(ctx, fileInfo.m_has_alpha_slices); - printf("Type enum: %d\n", type); basisu_image_info info; if (transcoder.get_image_info(data, size, info, 0)) { - uint32_t descW, descH, blocks; - if (transcoder.get_image_level_desc(data, size, 0, 0, descW, descH, blocks)) { - if (transcoder.start_transcoding(data, size)) { - uint32_t decSize = basis_get_bytes_per_block(type) * blocks; - if (void* decBuf = malloc(decSize)) { - if (type >= cTFTotalBlockTextureFormats) { - // note that blocks becomes total number of pixels for RGB/RGBA - blocks = descW * descH; + printf("Transcoding to type: %s (w: %d, h: %d, mips: %d)\n", + basis_get_format_name(type), info.m_width, info.m_height, + info.m_total_levels); + if (transcoder.start_transcoding(data, size)) { + uint32_t descW, descH, blocks; + for (uint32_t level = 0; level < info.m_total_levels; level++) { + // reset per level + success = false; + if (transcoder.get_image_level_desc(data, size, 0, level, descW, descH, blocks)) { + uint32_t decSize; + if (type == cTFPVRTC1_4_RGB || type == cTFPVRTC1_4_RGBA) { + decSize = (std::max(8U, (descW + 3) & ~3) * + std::max(8U, (descH + 3) & ~3) * 4 + 7) / 8; + } else { + decSize = basis_get_bytes_per_block(type) * blocks; } - if (transcoder.transcode_image_level(data, size, 0, 0, decBuf, blocks, type)) { - glBindTexture(GL_TEXTURE_2D, name); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - if (type < cTFTotalBlockTextureFormats) { - glCompressedTexImage2D(GL_TEXTURE_2D, 0, - toGlType(type), descW, descH, 0, decSize, decBuf); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - descW, descH, 0, GL_RGBA, toGlType(type), decBuf); + + if (void* decBuf = malloc(decSize)) { + if (type >= cTFTotalBlockTextureFormats) { + // note that blocks becomes total number of pixels for RGB/RGBA + blocks = descW * descH; } - success = true; + if (transcoder.transcode_image_level(data, size, 0, level, decBuf, blocks, type)) { + if (type < cTFTotalBlockTextureFormats) { + glCompressedTexImage2D(GL_TEXTURE_2D, level, + toGlType(type), descW, descH, 0, decSize, decBuf); + } else { + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, + descW, descH, 0, GL_RGBA, toGlType(type), decBuf); + } + success = true; + } + free(decBuf); } - free(decBuf); + } + if (!success) { + break; } } }