From 85fa18ec940b369791f2f39410da4c79f8c5108f Mon Sep 17 00:00:00 2001
From: Rich Geldreich
Date: Thu, 17 Dec 2020 14:26:28 -0500
Subject: [PATCH] Adding encoder WebAssembly support, encode_test sample
Encoder is now a library in the "encoder" directory JavaScript wrappers now
expose the entire codec: encoder, transcoder, container independent
transcoding, and .basis file information
---
CMakeLists.txt | 36 +-
README.md | 6 +
basisu.vcxproj | 75 +-
basisu.vcxproj.filters | 152 +-
basisu_tool.cpp | 22 +-
encoder/basisu_astc_decomp.cpp | 11 +
encoder/basisu_astc_decomp.h | 2 +-
encoder/basisu_backend.h | 6 +-
encoder/basisu_basis_file.cpp | 2 +-
encoder/basisu_basis_file.h | 2 +-
encoder/basisu_bc7enc.h | 2 +-
encoder/basisu_comp.cpp | 27 +-
encoder/basisu_comp.h | 22 +-
encoder/basisu_enc.cpp | 45 +-
encoder/basisu_enc.h | 13 +-
encoder/basisu_etc.h | 2 +-
encoder/basisu_frontend.cpp | 95 +-
encoder/basisu_frontend.h | 2 +-
.../basisu_global_selector_palette_helpers.h | 4 +-
encoder/basisu_gpu_texture.h | 2 +-
encoder/basisu_resample_filters.cpp | 20 +-
encoder/basisu_resampler.h | 2 +-
encoder/basisu_resampler_filters.h | 2 +-
encoder/basisu_uastc_enc.cpp | 22 +-
encoder/basisu_uastc_enc.h | 2 +-
transcoder/basisu_transcoder.cpp | 67 +-
transcoder/basisu_transcoder.h | 11 +-
transcoder/basisu_transcoder_uastc.h | 3 +
webgl/index.html | 3 +-
webgl/texture/index.html | 220 ++-
webgl/transcoder/CMakeLists.txt | 4 +-
webgl/transcoder/basis_wrappers.cpp | 1456 ++++++++++++++---
webgl/transcoder/build/basis_transcoder.js | 14 +-
webgl/transcoder/build/basis_transcoder.wasm | Bin 447033 -> 440267 bytes
webgl_videotest/basis.js | 21 +-
webgl_videotest/build.sh | 11 +-
36 files changed, 1922 insertions(+), 464 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d1e4562..3f632e3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,25 +54,25 @@ if (NOT MSVC)
endif()
set(BASISU_SRC_LIST ${COMMON_SRC_LIST}
- basisu_backend.cpp
- basisu_basis_file.cpp
- basisu_comp.cpp
- basisu_enc.cpp
- basisu_etc.cpp
- basisu_frontend.cpp
- basisu_global_selector_palette_helpers.cpp
- basisu_gpu_texture.cpp
- basisu_pvrtc1_4.cpp
- basisu_resampler.cpp
- basisu_resample_filters.cpp
- basisu_ssim.cpp
basisu_tool.cpp
- basisu_astc_decomp.cpp
- basisu_uastc_enc.cpp
- basisu_bc7enc.cpp
- lodepng.cpp
- apg_bmp.c
- jpgd.cpp
+ encoder/basisu_backend.cpp
+ encoder/basisu_basis_file.cpp
+ encoder/basisu_comp.cpp
+ encoder/basisu_enc.cpp
+ encoder/basisu_etc.cpp
+ encoder/basisu_frontend.cpp
+ encoder/basisu_global_selector_palette_helpers.cpp
+ encoder/basisu_gpu_texture.cpp
+ encoder/basisu_pvrtc1_4.cpp
+ encoder/basisu_resampler.cpp
+ encoder/basisu_resample_filters.cpp
+ encoder/basisu_ssim.cpp
+ encoder/basisu_astc_decomp.cpp
+ encoder/basisu_uastc_enc.cpp
+ encoder/basisu_bc7enc.cpp
+ encoder/lodepng.cpp
+ encoder/apg_bmp.c
+ encoder/jpgd.cpp
transcoder/basisu_transcoder.cpp
)
diff --git a/README.md b/README.md
index eda5f82..b9b8579 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,12 @@ The encoder uses [lodepng](https://lodev.org/lodepng/) for loading and saving PN
The encoder uses [tcuAstcUtil.cpp](https://chromium.googlesource.com/external/deqp/+/refs/heads/master/framework/common/tcuAstcUtil.cpp), from the [Android drawElements Quality Program (deqp) Testing Suite](https://source.android.com/devices/graphics/deqp-testing), for unpacking the transcoder's ASTC output for testing/validation purposes. This code is Copyright 2016 The Android Open Source Project, and uses the Apache 2.0 license. We have modified the code so it has no external dependencies, and disabled HDR support.
+### WebAssembly Support Using Emscripten
+
+Both the transcoder and now the compressor (as of 12/17/2020) may be compiled using emscripten to WebAssembly and used on the web. Currently, multithreading is not supported by the encoder when compiled with emscripten. An simple Web encoding demo is in webgl/encode_test.
+
+To enable compression support compile the JavaScript wrappers in webgl/transcoding/basis_wrappers.cpp with BASISU_SUPPORT_ENCODING set to 1. See the webgl/encoding directory.
+
### Legal/IP/license stuff
Basis Universal uses texture compression formats or technologies created by several companies: ARM Holdings, AMD, Ericsson, Microsoft, and Imagination Technologies Limited. All are supported by various open standards or API's from [The Khronos Group](https://www.khronos.org/), such as OpenGL 4.5, OpenGL ES, or Vulkan.
diff --git a/basisu.vcxproj b/basisu.vcxproj
index 3407176..f4ad5fd 100644
--- a/basisu.vcxproj
+++ b/basisu.vcxproj
@@ -147,52 +147,51 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/basisu.vcxproj.filters b/basisu.vcxproj.filters
index 1764b4b..4f7afed 100644
--- a/basisu.vcxproj.filters
+++ b/basisu.vcxproj.filters
@@ -1,44 +1,66 @@
-
-
-
-
-
-
-
-
-
-
-
-
transcoder
-
-
-
-
-
-
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
transcoder
@@ -51,15 +73,66 @@
transcoder
-
-
-
-
transcoder
-
-
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
+
+ encoder
+
@@ -91,5 +164,8 @@
{7a54aaad-1d10-4bdf-b8e9-c14ed2263ed8}
+
+ {518dd5c5-a7e1-4e79-8bb4-253e2d540c2c}
+
\ No newline at end of file
diff --git a/basisu_tool.cpp b/basisu_tool.cpp
index 3591ed2..aa168dc 100644
--- a/basisu_tool.cpp
+++ b/basisu_tool.cpp
@@ -18,15 +18,15 @@
#include "transcoder/basisu.h"
#include "transcoder/basisu_transcoder_internal.h"
-#include "basisu_enc.h"
-#include "basisu_etc.h"
-#include "basisu_gpu_texture.h"
-#include "basisu_frontend.h"
-#include "basisu_backend.h"
+#include "encoder/basisu_enc.h"
+#include "encoder/basisu_etc.h"
+#include "encoder/basisu_gpu_texture.h"
+#include "encoder/basisu_frontend.h"
+#include "encoder/basisu_backend.h"
#include "transcoder/basisu_global_selector_palette.h"
-#include "basisu_comp.h"
+#include "encoder/basisu_comp.h"
#include "transcoder/basisu_transcoder.h"
-#include "basisu_ssim.h"
+#include "encoder/basisu_ssim.h"
// Set BASISU_CATCH_EXCEPTIONS if you want exceptions to crash the app, otherwise main() catches them.
#define BASISU_CATCH_EXCEPTIONS 0
@@ -408,7 +408,7 @@ public:
else if (strcasecmp(pArg, "-force_alpha") == 0)
m_comp_params.m_force_alpha = true;
else if ((strcasecmp(pArg, "-separate_rg_to_color_alpha") == 0) ||
- (strcasecmp(pArg, "-seperate_rg_to_color_alpha") == 0)) // was mispelled for a while - whoops!
+ (strcasecmp(pArg, "-seperate_rg_to_color_alpha") == 0)) // was mispelled for a while - whoops!
{
m_comp_params.m_swizzle[0] = 0;
m_comp_params.m_swizzle[1] = 0;
@@ -1591,11 +1591,11 @@ static bool compare_mode(command_line_params &opts)
return true;
}
-#include "basisu_astc_decomp.h"
-#include "basisu_pvrtc1_4.h"
+#include "encoder/basisu_astc_decomp.h"
+#include "encoder/basisu_pvrtc1_4.h"
#define MINIZ_HEADER_FILE_ONLY
-#include "basisu_miniz.h"
+#include "encoder/basisu_miniz.h"
static bool bench_mode(command_line_params& opts)
{
#if 0
diff --git a/encoder/basisu_astc_decomp.cpp b/encoder/basisu_astc_decomp.cpp
index 81a1800..f8d40d7 100644
--- a/encoder/basisu_astc_decomp.cpp
+++ b/encoder/basisu_astc_decomp.cpp
@@ -50,6 +50,13 @@ typedef uint64_t deUint64;
#define DE_ASSERT assert
+#ifdef _MSC_VER
+#pragma warning (disable:4505) // unreferenced local function has been removed
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
namespace basisu_astc
{
static bool inBounds(int v, int l, int h)
@@ -1548,3 +1555,7 @@ bool decompress(uint8_t *pDst, const uint8_t * data, bool isSRGB, int blockWidth
} // astc
} // basisu_astc
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
\ No newline at end of file
diff --git a/encoder/basisu_astc_decomp.h b/encoder/basisu_astc_decomp.h
index 6cd053b..9ec2e46 100644
--- a/encoder/basisu_astc_decomp.h
+++ b/encoder/basisu_astc_decomp.h
@@ -23,7 +23,7 @@
* \brief ASTC Utilities.
*//*--------------------------------------------------------------------*/
-#include "transcoder/basisu.h" // to pick up the iterator debug level madness
+#include "../transcoder/basisu.h" // to pick up the iterator debug level madness
#include
#include
diff --git a/encoder/basisu_backend.h b/encoder/basisu_backend.h
index 171ca83..e8518e2 100644
--- a/encoder/basisu_backend.h
+++ b/encoder/basisu_backend.h
@@ -14,10 +14,10 @@
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#include "basisu_enc.h"
-#include "transcoder/basisu_transcoder_internal.h"
-#include "transcoder/basisu_global_selector_palette.h"
+#include "../transcoder/basisu_transcoder_internal.h"
+#include "../transcoder/basisu_global_selector_palette.h"
#include "basisu_frontend.h"
namespace basisu
diff --git a/encoder/basisu_basis_file.cpp b/encoder/basisu_basis_file.cpp
index ce6acd6..9662a9a 100644
--- a/encoder/basisu_basis_file.cpp
+++ b/encoder/basisu_basis_file.cpp
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "basisu_basis_file.h"
-#include "transcoder/basisu_transcoder.h"
+#include "../transcoder/basisu_transcoder.h"
// The output file version. Keep in sync with BASISD_SUPPORTED_BASIS_VERSION.
#define BASIS_FILE_VERSION (0x13)
diff --git a/encoder/basisu_basis_file.h b/encoder/basisu_basis_file.h
index df3abbd..7d9c577 100644
--- a/encoder/basisu_basis_file.h
+++ b/encoder/basisu_basis_file.h
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
-#include "transcoder/basisu_file_headers.h"
+#include "../transcoder/basisu_file_headers.h"
#include "basisu_backend.h"
namespace basisu
diff --git a/encoder/basisu_bc7enc.h b/encoder/basisu_bc7enc.h
index 0d7a090..3af606f 100644
--- a/encoder/basisu_bc7enc.h
+++ b/encoder/basisu_bc7enc.h
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "basisu_enc.h"
-#include "transcoder/basisu_transcoder_uastc.h"
+#include "../transcoder/basisu_transcoder_uastc.h"
namespace basisu
{
diff --git a/encoder/basisu_comp.cpp b/encoder/basisu_comp.cpp
index 7f39a66..fdaf3f0 100644
--- a/encoder/basisu_comp.cpp
+++ b/encoder/basisu_comp.cpp
@@ -202,8 +202,11 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(total_blocks, block_index_iter + N);
+ // FIXME: This sucks, but we're having a stack size related problem with std::function with emscripten.
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job([this, first_index, last_index, num_blocks_x, num_blocks_y, total_blocks, &source_image, &tex, &total_blocks_processed]
{
+#endif
BASISU_NOTE_UNUSED(num_blocks_y);
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
@@ -228,11 +231,16 @@ namespace basisu
}
}
+
+#ifndef __EMSCRIPTEN__
});
+#endif
} // block_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
if (m_params.m_rdo_uastc)
{
@@ -412,17 +420,16 @@ namespace basisu
m_params.m_swizzle[2] != 2 ||
m_params.m_swizzle[3] != 3)
{
- // Apply swizzle to incoming data
+ // Used for XY normal maps in RG - puts X in color, Y in alpha
for (uint32_t y = 0; y < file_image.get_height(); y++)
for (uint32_t x = 0; x < file_image.get_width(); x++)
{
const color_rgba &c = file_image(x, y);
file_image(x, y).set_noclamp_rgba(c[m_params.m_swizzle[0]], c[m_params.m_swizzle[1]], c[m_params.m_swizzle[2]], c[m_params.m_swizzle[3]]);
}
-
alpha_swizzled = m_params.m_swizzle[3] != 3;
}
-
+
bool has_alpha = false;
if (m_params.m_force_alpha || alpha_swizzled)
has_alpha = true;
@@ -636,14 +643,20 @@ namespace basisu
}
}
- printf("Total basis file slices: %u\n", (uint32_t)m_slice_descs.size());
+ if (m_params.m_status_output)
+ {
+ printf("Total basis file slices: %u\n", (uint32_t)m_slice_descs.size());
+ }
for (uint32_t i = 0; i < m_slice_descs.size(); i++)
{
const basisu_backend_slice_desc &slice_desc = m_slice_descs[i];
- printf("Slice: %u, alpha: %u, orig width/height: %ux%u, width/height: %ux%u, first_block: %u, image_index: %u, mip_level: %u, iframe: %u\n",
- i, slice_desc.m_alpha, slice_desc.m_orig_width, slice_desc.m_orig_height, slice_desc.m_width, slice_desc.m_height, slice_desc.m_first_block_index, slice_desc.m_source_file_index, slice_desc.m_mip_index, slice_desc.m_iframe);
+ if (m_params.m_status_output)
+ {
+ printf("Slice: %u, alpha: %u, orig width/height: %ux%u, width/height: %ux%u, first_block: %u, image_index: %u, mip_level: %u, iframe: %u\n",
+ i, slice_desc.m_alpha, slice_desc.m_orig_width, slice_desc.m_orig_height, slice_desc.m_width, slice_desc.m_height, slice_desc.m_first_block_index, slice_desc.m_source_file_index, slice_desc.m_mip_index, slice_desc.m_iframe);
+ }
if (m_any_source_image_has_alpha)
{
@@ -1222,7 +1235,6 @@ namespace basisu
const uint8_vec& comp_data = m_basis_file.get_compressed_data();
if (m_params.m_write_output_basis_files)
{
-
const std::string& basis_filename = m_params.m_out_filename;
if (!write_vec_to_file(basis_filename.c_str(), comp_data))
@@ -1233,6 +1245,7 @@ namespace basisu
printf("Wrote output .basis file \"%s\"\n", basis_filename.c_str());
}
+
size_t comp_size = 0;
if ((m_params.m_compute_stats) && (m_params.m_uastc) && (comp_data.size()))
{
diff --git a/encoder/basisu_comp.h b/encoder/basisu_comp.h
index aa77bef..7722e3f 100644
--- a/encoder/basisu_comp.h
+++ b/encoder/basisu_comp.h
@@ -16,8 +16,8 @@
#include "basisu_frontend.h"
#include "basisu_backend.h"
#include "basisu_basis_file.h"
-#include "transcoder/basisu_global_selector_palette.h"
-#include "transcoder/basisu_transcoder.h"
+#include "../transcoder/basisu_global_selector_palette.h"
+#include "../transcoder/basisu_transcoder.h"
#include "basisu_uastc_enc.h"
namespace basisu
@@ -41,6 +41,10 @@ namespace basisu
const uint32_t BASISU_MAX_SLICES = 0xFFFFFF;
+ const int BASISU_RDO_UASTC_DICT_SIZE_DEFAULT = 32768;
+ const int BASISU_RDO_UASTC_DICT_SIZE_MIN = 256;
+ const int BASISU_RDO_UASTC_DICT_SIZE_MAX = 65536;
+
struct image_stats
{
image_stats()
@@ -181,7 +185,7 @@ namespace basisu
T m_max;
bool m_changed;
};
-
+
struct basis_compressor_params
{
basis_compressor_params() :
@@ -199,7 +203,7 @@ namespace basisu
m_quality_level(-1),
m_pack_uastc_flags(cPackUASTCLevelDefault),
m_rdo_uastc_quality_scalar(1.0f, 0.001f, 10.0f),
- m_rdo_uastc_dict_size(32768, 256, 65536),
+ m_rdo_uastc_dict_size(BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX),
m_rdo_uastc_max_allowed_rms_increase_ratio(UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, .01f, 100.0f),
m_rdo_uastc_skip_block_rms_thresh(UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, .01f, 100.0f),
m_pJob_pool(nullptr)
@@ -212,6 +216,7 @@ namespace basisu
m_pSel_codebook = NULL;
m_uastc.clear();
+ m_status_output.clear();
m_source_filenames.clear();
m_source_alpha_filenames.clear();
@@ -298,6 +303,9 @@ namespace basisu
// Flip images across Y axis
bool_param m_y_flip;
+
+ // If true, the compressor will print basis status to stdout during compression.
+ bool_param m_status_output;
// Output debug information during compression
bool_param m_debug;
@@ -339,8 +347,8 @@ namespace basisu
// Always put alpha slices in the output basis file, even when the input doesn't have alpha
bool_param m_force_alpha;
bool_param m_multithreading;
-
- // Swizzle incoming channels
+
+ // Split the R channel to RGB and the G channel to alpha, then write a basis file with alpha channels
char m_swizzle[4];
bool_param m_renormalize;
@@ -363,7 +371,7 @@ namespace basisu
param m_mip_smallest_dimension;
// Codebook size (quality) control.
- // If m_quality_level != -1, it controls the quality level. It ranges from [0,255].
+ // If m_quality_level != -1, it controls the quality level. It ranges from [0,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
// Otherwise m_max_endpoint_clusters/m_max_selector_clusters controls the codebook sizes directly.
uint32_t m_max_endpoint_clusters;
uint32_t m_max_selector_clusters;
diff --git a/encoder/basisu_enc.cpp b/encoder/basisu_enc.cpp
index 0c5f883..87b69dc 100644
--- a/encoder/basisu_enc.cpp
+++ b/encoder/basisu_enc.cpp
@@ -17,7 +17,7 @@
#include "basisu_resampler.h"
#include "basisu_resampler_filters.h"
#include "basisu_etc.h"
-#include "transcoder/basisu_transcoder.h"
+#include "../transcoder/basisu_transcoder.h"
#include "basisu_bc7enc.h"
#include "apg_bmp.h"
#include "jpgd.h"
@@ -282,38 +282,36 @@ namespace basisu
return true;
}
-
- bool load_png(const char* pFilename, image& img)
+
+ bool load_png(const uint8_t *pBuf, size_t buf_size, image &img, const char *pFilename)
{
- std::vector buffer;
- unsigned err = lodepng::load_file(buffer, std::string(pFilename));
- if (err)
+ if (!buf_size)
return false;
- unsigned w = 0, h = 0;
-
- if (sizeof(void *) == sizeof(uint32_t))
+ unsigned err = 0, w = 0, h = 0;
+
+ if (sizeof(void*) == sizeof(uint32_t))
{
// Inspect the image first on 32-bit builds, to see if the image would require too much memory.
lodepng::State state;
- err = lodepng_inspect(&w, &h, &state, &buffer[0], buffer.size());
+ err = lodepng_inspect(&w, &h, &state, pBuf, buf_size);
if ((err != 0) || (!w) || (!h))
return false;
const uint32_t exepected_alloc_size = w * h * sizeof(uint32_t);
-
+
// If the file is too large on 32-bit builds then just bail now, to prevent causing a memory exception.
if (exepected_alloc_size >= MAX_32BIT_ALLOC_SIZE)
{
- error_printf("Image \"%s\" is too large (%ux%u) to process in a 32-bit build!\n", pFilename, w, h);
+ error_printf("Image \"%s\" is too large (%ux%u) to process in a 32-bit build!\n", (pFilename != nullptr) ? pFilename : "", w, h);
return false;
}
-
+
w = h = 0;
}
-
+
std::vector out;
- err = lodepng::decode(out, w, h, &buffer[0], buffer.size());
+ err = lodepng::decode(out, w, h, pBuf, buf_size);
if ((err != 0) || (!w) || (!h))
return false;
@@ -326,6 +324,17 @@ namespace basisu
return true;
}
+
+ bool load_png(const char* pFilename, image& img)
+ {
+ std::vector buffer;
+ unsigned err = lodepng::load_file(buffer, std::string(pFilename));
+ if (err)
+ return false;
+
+
+ return load_png(buffer.data(), buffer.size(), img, pFilename);
+ }
bool load_jpg(const char *pFilename, image& img)
{
@@ -391,7 +400,7 @@ namespace basisu
if ((!has_alpha) || ((image_save_flags & cImageSaveIgnoreAlpha) != 0))
{
const uint64_t total_bytes = (uint64_t)img.get_width() * 3U * (uint64_t)img.get_height();
- uint8_vec rgb_pixels(total_bytes);
+ uint8_vec rgb_pixels(static_cast(total_bytes));
uint8_t *pDst = &rgb_pixels[0];
for (uint32_t y = 0; y < img.get_height(); y++)
@@ -1464,13 +1473,15 @@ namespace basisu
std::unique_lock lock(m_mutex);
m_queue.emplace_back(std::move(job));
-
+
const size_t queue_size = m_queue.size();
lock.unlock();
if (queue_size > 1)
+ {
m_has_work.notify_one();
+ }
}
void job_pool::wait_for_all()
diff --git a/encoder/basisu_enc.h b/encoder/basisu_enc.h
index 80a8074..58719ad 100644
--- a/encoder/basisu_enc.h
+++ b/encoder/basisu_enc.h
@@ -13,8 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
-#include "transcoder/basisu_transcoder_internal.h"
+#include "../transcoder/basisu.h"
+#include "../transcoder/basisu_transcoder_internal.h"
#include
#include
@@ -1690,7 +1690,9 @@ namespace basisu
for (uint32_t thread_iter = 0; thread_iter < max_threads; thread_iter++)
{
+#ifndef __EMSCRIPTEN__
pJob_pool->add_job( [thread_iter, &local_clusters, &local_parent_clusters, &success_flags, &quantizers, &initial_codebook, &q, &limit_clusterizers, &max_codebook_size, &max_threads, &max_parent_codebook_size] {
+#endif
Quantizer& lq = quantizers[thread_iter];
uint_vec& cluster_indices = initial_codebook[thread_iter];
@@ -1731,11 +1733,15 @@ namespace basisu
}
}
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // thread_iter
+#ifndef __EMSCRIPTEN__
pJob_pool->wait_for_all();
+#endif
uint32_t total_clusters = 0, total_parent_clusters = 0;
@@ -2856,7 +2862,8 @@ namespace basisu
};
// Image saving/loading/resampling
-
+
+ bool load_png(const uint8_t* pBuf, size_t buf_size, image& img, const char* pFilename = nullptr);
bool load_png(const char* pFilename, image& img);
inline bool load_png(const std::string &filename, image &img) { return load_png(filename.c_str(), img); }
diff --git a/encoder/basisu_etc.h b/encoder/basisu_etc.h
index d8b0468..0c8a7be 100644
--- a/encoder/basisu_etc.h
+++ b/encoder/basisu_etc.h
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#include "basisu_enc.h"
#include
diff --git a/encoder/basisu_frontend.cpp b/encoder/basisu_frontend.cpp
index b09aa61..35ad68f 100644
--- a/encoder/basisu_frontend.cpp
+++ b/encoder/basisu_frontend.cpp
@@ -17,7 +17,7 @@
// This code originally supported full ETC1 and ETC1S, so there's some legacy stuff to be cleaned up in here.
// Add endpoint tiling support (where we force adjacent blocks to use the same endpoints during quantization), for a ~10% or more increase in bitrate at same SSIM. The backend already supports this.
//
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#include "basisu_frontend.h"
#include
#include
@@ -78,6 +78,7 @@ namespace basisu
{
if (!p.m_pGlobal_sel_codebook)
{
+ debug_printf("basisu_frontend::init: No global sel codebook!\n");
assert(0);
return false;
}
@@ -481,8 +482,10 @@ namespace basisu
{
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -507,7 +510,7 @@ namespace basisu
optimizer.init(optimizer_params, optimizer_results);
optimizer.compute();
-
+
etc_block &blk = m_etc1_blocks_etc1s[block_index];
memset(&blk, 0, sizeof(blk));
@@ -520,10 +523,15 @@ namespace basisu
blk.set_selector(x, y, selectors[x + y * 4]);
}
+#ifndef __EMSCRIPTEN__
} );
+#endif
+
}
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
}
void basisu_frontend::init_endpoint_training_vectors()
@@ -540,7 +548,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &training_vecs] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -562,11 +572,15 @@ namespace basisu
} // block_index;
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // block_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
}
void basisu_frontend::generate_endpoint_clusters()
@@ -707,7 +721,9 @@ namespace basisu
const uint32_t first_index = cluster_index_iter;
const uint32_t last_index = minimum((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+#endif
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
@@ -775,10 +791,15 @@ namespace basisu
}
} // cluster_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
+
} // cluster_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
vector_sort(m_subblock_endpoint_quant_err_vec);
}
@@ -893,8 +914,10 @@ namespace basisu
{
const uint32_t first_index = cluster_index_iter;
const uint32_t last_index = minimum((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, step ] {
+#endif
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
@@ -1012,11 +1035,15 @@ namespace basisu
} // cluster_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // cluster_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
}
bool basisu_frontend::check_etc1s_constraints() const
@@ -1081,7 +1108,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &best_cluster_indices, &block_clusters] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -1154,12 +1183,16 @@ namespace basisu
best_cluster_indices[block_index] = best_cluster_index;
} // block_index
-
+
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // block_index_iter
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
std::vector > optimized_endpoint_clusters(m_endpoint_clusters.size());
uint32_t total_subblocks_reassigned = 0;
@@ -1264,7 +1297,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -1288,12 +1323,16 @@ namespace basisu
blk.determine_selectors(pSource_pixels, m_params.m_perceptual);
} // block_index
-
+
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // block_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
m_orig_encoded_blocks = m_encoded_blocks;
}
@@ -1355,7 +1394,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &training_vecs] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -1382,11 +1423,15 @@ namespace basisu
} // block_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // block_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
vec16F_clusterizer selector_clusterizer;
for (uint32_t i = 0; i < m_total_blocks; i++)
@@ -1474,8 +1519,10 @@ namespace basisu
{
const uint32_t first_index = cluster_index_iter;
const uint32_t last_index = minimum((uint32_t)total_selector_clusters, cluster_index_iter + N);
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &total_clusters_processed, &total_selector_clusters] {
+#endif
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
@@ -1528,11 +1575,15 @@ namespace basisu
} // cluster_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // cluster_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
}
else
{
@@ -1552,8 +1603,10 @@ namespace basisu
{
const uint32_t first_index = cluster_index_iter;
const uint32_t last_index = minimum((uint32_t)total_selector_clusters, cluster_index_iter + N);
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &uses_hybrid_sel_codebook, &total_clusters_processed, &total_selector_clusters] {
+#endif
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
@@ -1667,11 +1720,15 @@ namespace basisu
} // cluster_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // cluster_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
} // if (m_params.m_pGlobal_sel_codebook)
@@ -1741,7 +1798,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(m_total_blocks, first_index + N);
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &new_cluster_indices] {
+#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
@@ -1804,11 +1863,15 @@ namespace basisu
} // block_index
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // block_index_iter
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
m_selector_cluster_indices.swap(new_cluster_indices);
}
@@ -2112,8 +2175,11 @@ namespace basisu
{
const uint32_t first_index = cluster_index_iter;
const uint32_t last_index = minimum((uint32_t)new_endpoint_cluster_block_indices.size(), cluster_index_iter + N);
-
+
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &cluster_improved, &cluster_valid, &new_endpoint_cluster_block_indices, &pBlock_selector_indices ] {
+#endif
+
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
const std::vector& cluster_block_indices = new_endpoint_cluster_block_indices[cluster_index];
@@ -2198,11 +2264,16 @@ namespace basisu
cluster_valid[cluster_index] = true;
} // cluster_index
+
+#ifndef __EMSCRIPTEN__
} );
+#endif
} // cluster_index_iter
+#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
+#endif
uint32_t total_unused_clusters = 0;
uint32_t total_improved_clusters = 0;
diff --git a/encoder/basisu_frontend.h b/encoder/basisu_frontend.h
index e4ccf14..e5f7954 100644
--- a/encoder/basisu_frontend.h
+++ b/encoder/basisu_frontend.h
@@ -17,7 +17,7 @@
#include "basisu_etc.h"
#include "basisu_gpu_texture.h"
#include "basisu_global_selector_palette_helpers.h"
-#include "transcoder/basisu_file_headers.h"
+#include "../transcoder/basisu_file_headers.h"
namespace basisu
{
diff --git a/encoder/basisu_global_selector_palette_helpers.h b/encoder/basisu_global_selector_palette_helpers.h
index 32692c5..9e9cdbd 100644
--- a/encoder/basisu_global_selector_palette_helpers.h
+++ b/encoder/basisu_global_selector_palette_helpers.h
@@ -14,9 +14,9 @@
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#include "basisu_etc.h"
-#include "transcoder/basisu_global_selector_palette.h"
+#include "../transcoder/basisu_global_selector_palette.h"
namespace basisu
{
diff --git a/encoder/basisu_gpu_texture.h b/encoder/basisu_gpu_texture.h
index 7cf2b41..7ca9272 100644
--- a/encoder/basisu_gpu_texture.h
+++ b/encoder/basisu_gpu_texture.h
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#include "basisu_etc.h"
namespace basisu
diff --git a/encoder/basisu_resample_filters.cpp b/encoder/basisu_resample_filters.cpp
index 39df8bd..c0adb13 100644
--- a/encoder/basisu_resample_filters.cpp
+++ b/encoder/basisu_resample_filters.cpp
@@ -310,10 +310,22 @@ namespace basisu
const resample_filter g_resample_filters[] =
{
- { "box", box_filter, BOX_FILTER_SUPPORT }, { "tent", tent_filter, TENT_FILTER_SUPPORT }, { "bell", bell_filter, BELL_SUPPORT }, { "b-spline", B_spline_filter, B_SPLINE_SUPPORT },
- { "mitchell", mitchell_filter, MITCHELL_SUPPORT }, { "lanczos3", lanczos3_filter, LANCZOS3_SUPPORT }, { "blackman", blackman_filter, BLACKMAN_SUPPORT }, { "lanczos4", lanczos4_filter, LANCZOS4_SUPPORT },
- { "lanczos6", lanczos6_filter, LANCZOS6_SUPPORT }, { "lanczos12", lanczos12_filter, LANCZOS12_SUPPORT }, { "kaiser", kaiser_filter, KAISER_SUPPORT }, { "gaussian", gaussian_filter, GAUSSIAN_SUPPORT },
- { "catmullrom", catmull_rom_filter, CATMULL_ROM_SUPPORT }, { "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT }, { "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT }, { "quadratic_mix", quadratic_mix_filter, QUADRATIC_SUPPORT },
+ { "box", box_filter, BOX_FILTER_SUPPORT },
+ { "tent", tent_filter, TENT_FILTER_SUPPORT },
+ { "bell", bell_filter, BELL_SUPPORT },
+ { "b-spline", B_spline_filter, B_SPLINE_SUPPORT },
+ { "mitchell", mitchell_filter, MITCHELL_SUPPORT },
+ { "blackman", blackman_filter, BLACKMAN_SUPPORT },
+ { "lanczos3", lanczos3_filter, LANCZOS3_SUPPORT },
+ { "lanczos4", lanczos4_filter, LANCZOS4_SUPPORT },
+ { "lanczos6", lanczos6_filter, LANCZOS6_SUPPORT },
+ { "lanczos12", lanczos12_filter, LANCZOS12_SUPPORT },
+ { "kaiser", kaiser_filter, KAISER_SUPPORT },
+ { "gaussian", gaussian_filter, GAUSSIAN_SUPPORT },
+ { "catmullrom", catmull_rom_filter, CATMULL_ROM_SUPPORT },
+ { "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT },
+ { "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT },
+ { "quadratic_mix", quadratic_mix_filter, QUADRATIC_SUPPORT },
};
const int g_num_resample_filters = BASISU_ARRAY_SIZE(g_resample_filters);
diff --git a/encoder/basisu_resampler.h b/encoder/basisu_resampler.h
index c3f2e05..dc0978c 100644
--- a/encoder/basisu_resampler.h
+++ b/encoder/basisu_resampler.h
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
#define BASISU_RESAMPLER_DEBUG_OPS (0)
#define BASISU_RESAMPLER_DEFAULT_FILTER "lanczos4"
diff --git a/encoder/basisu_resampler_filters.h b/encoder/basisu_resampler_filters.h
index 5659c5f..0ebb51c 100644
--- a/encoder/basisu_resampler_filters.h
+++ b/encoder/basisu_resampler_filters.h
@@ -14,7 +14,7 @@
// limitations under the License.
#pragma once
-#include "transcoder/basisu.h"
+#include "../transcoder/basisu.h"
namespace basisu
{
diff --git a/encoder/basisu_uastc_enc.cpp b/encoder/basisu_uastc_enc.cpp
index c4fb9eb..9b75b84 100644
--- a/encoder/basisu_uastc_enc.cpp
+++ b/encoder/basisu_uastc_enc.cpp
@@ -3098,6 +3098,11 @@ namespace basisu
void encode_uastc(const uint8_t* pRGBAPixels, uastc_block& output_block, uint32_t flags)
{
+// printf("encode_uastc: \n");
+// for (int i = 0; i < 16; i++)
+// printf("[%u %u %u %u] ", pRGBAPixels[i * 4 + 0], pRGBAPixels[i * 4 + 1], pRGBAPixels[i * 4 + 2], pRGBAPixels[i * 4 + 3]);
+// printf("\n");
+
const color_rgba(*block)[4] = reinterpret_cast(pRGBAPixels);
bool solid_color = true, has_alpha = false, is_la = true;
@@ -3139,6 +3144,8 @@ namespace basisu
pack_uastc(output_block, solid_results, etc1_blk, etc1_bias, eac_a8_blk, false, false);
+// printf(" Solid\n");
+
return;
}
@@ -3594,7 +3601,13 @@ namespace basisu
// Finally, pack the UASTC block with its hints and we're done.
pack_uastc(output_block, best_results, etc1_blk, etc1_bias, eac_a8_blk, bc1_hint0, bc1_hint1);
+
+// printf(" Packed: ");
+// for (int i = 0; i < 16; i++)
+// printf("%X ", output_block.m_bytes[i]);
+// printf("\n");
}
+
static bool uastc_recompute_hints(basist::uastc_block* pBlock, const color_rgba* pBlock_pixels, uint32_t flags, const unpacked_uastc_block *pUnpacked_blk)
{
unpacked_uastc_block unpacked_blk;
@@ -3761,7 +3774,7 @@ namespace basisu
{
std::size_t operator()(selector_bitsequence const& s) const noexcept
{
- return hash_hsieh((uint8_t *)&s, sizeof(s)) ^ s.m_sel;
+ return static_cast(hash_hsieh((uint8_t *)&s, sizeof(s)) ^ s.m_sel);
}
};
@@ -4053,7 +4066,9 @@ namespace basisu
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum(num_blocks, block_index_iter + blocks_per_job);
+#ifndef __EMSCRIPTEN__
pJob_pool->add_job([first_index, last_index, pBlocks, pBlock_pixels, ¶ms, flags, &total_skipped, &total_modified, &total_refined, &all_succeeded, &stat_mutex] {
+#endif
uint32_t job_skipped = 0, job_modified = 0, job_refined = 0;
@@ -4068,11 +4083,16 @@ namespace basisu
total_refined += job_refined;
}
+#ifndef __EMSCRIPTEN__
}
);
+#endif
+
} // block_index_iter
+#ifndef __EMSCRIPTEN__
pJob_pool->wait_for_all();
+#endif
status = all_succeeded;
}
diff --git a/encoder/basisu_uastc_enc.h b/encoder/basisu_uastc_enc.h
index 0ccad7d..eeb2525 100644
--- a/encoder/basisu_uastc_enc.h
+++ b/encoder/basisu_uastc_enc.h
@@ -15,7 +15,7 @@
#pragma once
#include "basisu_etc.h"
-#include "transcoder/basisu_transcoder_uastc.h"
+#include "../transcoder/basisu_transcoder_uastc.h"
namespace basisu
{
diff --git a/transcoder/basisu_transcoder.cpp b/transcoder/basisu_transcoder.cpp
index 9366f0a..a77bb82 100644
--- a/transcoder/basisu_transcoder.cpp
+++ b/transcoder/basisu_transcoder.cpp
@@ -9577,7 +9577,7 @@ namespace basist
uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
uint32_t slice_offset, uint32_t slice_length,
uint32_t decode_flags,
- bool basis_file_has_alpha_slices,
+ bool has_alpha,
bool is_video,
uint32_t output_row_pitch_in_blocks_or_pixels,
basisu_transcoder_state* pState,
@@ -9603,7 +9603,7 @@ namespace basist
}
}
- if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!basis_file_has_alpha_slices))
+ if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!has_alpha))
{
// Switch to PVRTC1 RGB if the input doesn't have alpha.
target_format = transcoder_texture_format::cTFPVRTC1_4_RGB;
@@ -9628,7 +9628,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC1,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
if (!status)
{
@@ -9640,7 +9640,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_RGBA, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_RGBA,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to ETC2 failed\n");
@@ -9652,7 +9652,7 @@ namespace basist
// TODO: ETC1S allows BC1 from alpha channel. That doesn't seem actually useful, though.
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC1,
- bytes_per_block_or_pixel, true, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
+ bytes_per_block_or_pixel, true, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC1 failed\n");
@@ -9663,7 +9663,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC3, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC3,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC3 failed\n");
@@ -9674,10 +9674,10 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState,
// nullptr, 0,
- // ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
+ // ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC4,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
- ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
+ ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC4 failed\n");
@@ -9690,7 +9690,7 @@ namespace basist
// nullptr, 0,
// 0, 3);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC5,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
0, 3);
if (!status)
{
@@ -9703,7 +9703,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC7,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC7 failed\n");
@@ -9714,7 +9714,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cPVRTC1_4_RGB,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to PVRTC1 RGB 4bpp failed\n");
@@ -9725,7 +9725,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGBA, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cPVRTC1_4_RGBA,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to PVRTC1 RGBA 4bpp failed\n");
@@ -9736,7 +9736,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cASTC_4x4,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to ASTC 4x4 failed\n");
@@ -9768,10 +9768,10 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState,
// nullptr, 0,
- // ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
+ // ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_EAC_R11,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
- ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
+ ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to EAC R11 failed\n");
@@ -9784,7 +9784,7 @@ namespace basist
// nullptr, 0,
// 0, 3);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_EAC_RG11,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels,
0, 3);
if (!status)
{
@@ -9796,7 +9796,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA32, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGBA32,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGBA32 failed\n");
@@ -9807,7 +9807,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGB565, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGB565,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGB565 failed\n");
@@ -9818,7 +9818,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBGR565, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBGR565,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGB565 failed\n");
@@ -9829,7 +9829,7 @@ namespace basist
{
//status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA4444, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGBA4444,
- bytes_per_block_or_pixel, false, basis_file_has_alpha_slices, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
+ bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels);
if (!status)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGBA4444 failed\n");
@@ -10239,6 +10239,21 @@ namespace basist
image_info.m_total_blocks = image_info.m_num_blocks_x * image_info.m_num_blocks_y;
image_info.m_first_slice_index = slice_index;
+ image_info.m_rgb_file_ofs = slice_desc.m_file_ofs;
+ image_info.m_rgb_file_len = slice_desc.m_file_size;
+ image_info.m_alpha_file_ofs = 0;
+ image_info.m_alpha_file_len = 0;
+
+ if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S)
+ {
+ if (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices)
+ {
+ assert((slice_index + 1) < (int)pHeader->m_total_slices);
+ image_info.m_alpha_file_ofs = pSlice_descs[slice_index + 1].m_file_ofs;
+ image_info.m_alpha_file_len = pSlice_descs[slice_index + 1].m_file_size;
+ }
+ }
+
return true;
}
@@ -10258,11 +10273,14 @@ namespace basist
file_info.m_total_header_size = sizeof(basis_file_header) + pHeader->m_total_slices * sizeof(basis_slice_desc);
file_info.m_total_selectors = pHeader->m_total_selectors;
+ file_info.m_selector_codebook_ofs = pHeader->m_selector_cb_file_ofs;
file_info.m_selector_codebook_size = pHeader->m_selector_cb_file_size;
file_info.m_total_endpoints = pHeader->m_total_endpoints;
+ file_info.m_endpoint_codebook_ofs = pHeader->m_endpoint_cb_file_ofs;
file_info.m_endpoint_codebook_size = pHeader->m_endpoint_cb_file_size;
+ file_info.m_tables_ofs = pHeader->m_tables_file_ofs;
file_info.m_tables_size = pHeader->m_tables_file_size;
file_info.m_tex_format = static_cast(static_cast(pHeader->m_tex_format));
@@ -12454,7 +12472,12 @@ namespace basist
bits = read_bits64(blk.m_bytes, bit_ofs, std::min(64, 128 - (int)bit_ofs));
else
{
+#ifdef __EMSCRIPTEN__
+ bits = blk.m_dwords[2];
+ bits |= (((uint64_t)blk.m_dwords[3]) << 32U);
+#else
bits = blk.m_qwords[1];
+#endif
if (bit_ofs >= 64U)
bits >>= (bit_ofs - 64U);
diff --git a/transcoder/basisu_transcoder.h b/transcoder/basisu_transcoder.h
index 41e7c39..a58ca08 100644
--- a/transcoder/basisu_transcoder.h
+++ b/transcoder/basisu_transcoder.h
@@ -280,7 +280,7 @@ namespace basist
uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
uint32_t slice_offset, uint32_t slice_length,
uint32_t decode_flags = 0,
- bool basis_file_has_alpha_slices = false,
+ bool has_alpha = false,
bool is_video = false,
uint32_t output_row_pitch_in_blocks_or_pixels = 0,
basisu_transcoder_state* pState = nullptr,
@@ -351,6 +351,11 @@ namespace basist
uint32_t m_total_blocks;
uint32_t m_first_slice_index;
+
+ uint32_t m_rgb_file_ofs;
+ uint32_t m_rgb_file_len;
+ uint32_t m_alpha_file_ofs;
+ uint32_t m_alpha_file_len;
bool m_alpha_flag; // true if the image has alpha data
bool m_iframe_flag; // true if the image is an I-Frame
@@ -362,12 +367,16 @@ namespace basist
uint32_t m_total_header_size;
uint32_t m_total_selectors;
+ uint32_t m_selector_codebook_ofs;
uint32_t m_selector_codebook_size;
uint32_t m_total_endpoints;
+ uint32_t m_endpoint_codebook_ofs;
uint32_t m_endpoint_codebook_size;
+ uint32_t m_tables_ofs;
uint32_t m_tables_size;
+
uint32_t m_slices_size;
basis_texture_type m_tex_type;
diff --git a/transcoder/basisu_transcoder_uastc.h b/transcoder/basisu_transcoder_uastc.h
index 7d520dc..d501a2a 100644
--- a/transcoder/basisu_transcoder_uastc.h
+++ b/transcoder/basisu_transcoder_uastc.h
@@ -205,7 +205,10 @@ namespace basist
{
uint8_t m_bytes[16];
uint32_t m_dwords[4];
+
+#ifndef __EMSCRIPTEN__
uint64_t m_qwords[2];
+#endif
};
};
diff --git a/webgl/index.html b/webgl/index.html
index 4273e04..cfb482e 100644
--- a/webgl/index.html
+++ b/webgl/index.html
@@ -11,5 +11,6 @@
diff --git a/webgl/texture/index.html b/webgl/texture/index.html
index b0d7473..b346ece 100644
--- a/webgl/texture/index.html
+++ b/webgl/texture/index.html
@@ -103,6 +103,7 @@ COMPRESSED_RGB_ETC1_WEBGL = 0x8D64;
COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
+// Same as the Module.transcoder_texture_format enum
BASIS_FORMAT = {
cTFETC1: 0,
cTFETC2: 1,
@@ -120,6 +121,11 @@ BASIS_FORMAT = {
cTFRGB565: 14,
cTFBGR565: 15,
cTFRGBA4444: 16,
+ cTFFXT1_RGB: 17,
+ cTFPVRTC2_4_RGB: 18,
+ cTFPVRTC2_4_RGBA: 19,
+ cTFETC2_EAC_R11: 20,
+ cTFETC2_EAC_RG11: 21
};
BASIS_FORMAT_NAMES = {};
@@ -149,6 +155,61 @@ function redraw()
renderer.drawTexture(tex, displayWidth, displayHeight, drawMode);
}
+function dumpBasisFileDesc(basisFile)
+{
+ var basisFileDesc = basisFile.getFileDesc();
+
+ log('------');
+ log('getFileDesc():');
+ log('version: ' + basisFileDesc.version);
+ log('us per frame: ' + basisFileDesc.usPerFrame);
+ log('total images: ' + basisFileDesc.totalImages);
+ log('userdata0: ' + basisFileDesc.userdata0 + ' userdata1: ' + basisFileDesc.userdata1);
+ log('texFormat: ' + basisFileDesc.texFormat);
+ log('yFlipped: ' + basisFileDesc.yFlipped + ' hasAlphaSlices: ' + basisFileDesc.hasAlphaSlices);
+
+ if (basisFileDesc.texFormat == Module.basis_tex_format.cETC1S.value)
+ {
+ log('numEndpoints: ' + basisFileDesc.numEndpoints);
+ log('endpointPaletteOfs: ' + basisFileDesc.endpointPaletteOfs);
+ log('endpointPaletteLen: ' + basisFileDesc.endpointPaletteLen);
+ log('numSelectors: ' + basisFileDesc.numSelectors);
+ log('selectorPaletteOfs: ' + basisFileDesc.selectorPaletteOfs);
+ log('selectorPaletteLen: ' + basisFileDesc.selectorPaletteLen);
+ log('tablesOfs: ' + basisFileDesc.tablesOfs);
+ log('tablesLen: ' + basisFileDesc.tablesLen);
+ }
+ log('------');
+ log('getImageDesc() for all images:');
+ var image_index;
+ for (image_index = 0; image_index < basisFileDesc.totalImages; image_index++)
+ {
+ log('image: ' + image_index);
+
+ var basisImageDesc = basisFile.getImageDesc(image_index);
+
+ log('origWidth: ' + basisImageDesc.origWidth + ' origWidth: ' + basisImageDesc.origHeight);
+ log('numBlocksX: ' + basisImageDesc.numBlocksX + ' origWidth: ' + basisImageDesc.numBlocksY);
+ log('numLevels: ' + basisImageDesc.numLevels);
+ log('alphaFlag: ' + basisImageDesc.alphaFlag + ' iframeFlag: ' + basisImageDesc.iframeFlag);
+
+ log('getImageLevelDesc() for all mipmap levels:');
+ var level_index;
+ for (level_index = 0; level_index < basisImageDesc.numLevels; level_index++)
+ {
+ var basisImageLevelDesc = basisFile.getImageLevelDesc(image_index, level_index);
+
+ log('level: ' + level_index +
+ ' rgb_file_offset: ' + basisImageLevelDesc.rgbFileOfs + ' rgb_file_len: ' + basisImageLevelDesc.rgbFileLen);
+
+ if (basisFileDesc.hasAlphaSlices)
+ log('alpha_file_offset: ' + basisImageLevelDesc.alphaFileOfs + ' alpha_file_len: ' + basisImageLevelDesc.alphaFileLen);
+ }
+ }
+
+ log('------');
+}
+
function dataLoaded(data)
{
log('Done loading .basis file, decoded header:');
@@ -165,7 +226,9 @@ function dataLoaded(data)
images = basisFile.getNumImages();
levels = basisFile.getNumLevels(0);
has_alpha = basisFile.getHasAlpha();
-
+
+ dumpBasisFileDesc(basisFile);
+
if (!width || !height || !images || !levels) {
console.warn('Invalid .basis file');
basisFile.close();
@@ -237,6 +300,8 @@ function dataLoaded(data)
}
elem('format').innerText = formatString;
+
+ log('format: ' + format);
if (!basisFile.startTranscoding()) {
log('startTranscoding failed');
@@ -245,20 +310,146 @@ function dataLoaded(data)
basisFile.delete();
return;
}
-
+
+ const isUncompressedFormat = Module.formatIsUncompressed(format);
+
+ const blockWidth = isUncompressedFormat ? 1 : 4, blockHeight = isUncompressedFormat ? 1 : 4;
+
+ const bytesPerBlockOrPixel = Module.getBytesPerBlockOrPixel(format);
+ log('isUncompressedFormat: ' + isUncompressedFormat + ' bytesPerBlockOrPixel: ' + bytesPerBlockOrPixel);
+
const dstSize = basisFile.getImageTranscodedSizeInBytes(0, 0, format);
const dst = new Uint8Array(dstSize);
- log(dstSize);
+// log('getImageTranscodedSizeInBytes() returned ' + dstSize);
-// if (!basisFile.transcodeImage(dst, 0, 0, format, 1, 0)) {
- if (!basisFile.transcodeImage(dst, 0, 0, format, 0, 0)) {
- log('basisFile.transcodeImage failed');
- console.warn('transcodeImage failed');
- basisFile.close();
- basisFile.delete();
-
- return;
+ // Use the low or high level transcoding API's. The high level API's require .basis files, while the low-level API's just work off blobs of memory and parameters.
+ if (elem('ContainerIndependentTranscoding').checked)
+ {
+ // Always transcode the first image and the first mipmap level
+ const image_index = 0;
+ const level_index = 0;
+
+ // Get the .basis file description
+ var basisFileDesc = basisFile.getFileDesc();
+
+ // Get the description of the file's first image (there could be multiple images, for texture arrays or videos)
+ var basisImageDesc = basisFile.getImageDesc(image_index);
+
+ // Get the description of this image's mipmap level
+ var basisImageLevelDesc = basisFile.getImageLevelDesc(image_index, level_index);
+
+ var status = false;
+
+ // If we're transcoding to ETC1S, use the LowLevelETC1SImageTranscoder class. Otherwise use the transcodeUASTCImage() function.
+ if (basisFileDesc.texFormat == Module.basis_tex_format.cETC1S.value)
+ {
+ // Create an instance of the LowLevelETC1SImageTranscoder class.
+ const etc1s_transcoder = new Module.LowLevelETC1SImageTranscoder();
+
+ // Create Uint8Array's pointing into the various bits of the .basis file holding the compressed data for the codebooks and the Huffman tables.
+ var selectorPalette = new Uint8Array(data, basisFileDesc.selectorPaletteOfs, basisFileDesc.selectorPaletteLen);
+ var endpointPalette = new Uint8Array(data, basisFileDesc.endpointPaletteOfs, basisFileDesc.endpointPaletteLen);
+ var tables = new Uint8Array(data, basisFileDesc.tablesOfs, basisFileDesc.tablesLen);
+
+ // Create a Uint8Array pointing to the image's compressed data.
+ // If it's an opaque .basis file, there will only be RGB data. For transparant .basis files, each RGB slice will be immediately followed by an alpha slice.
+ // Compressed ETC1S alpha data is guaranteed to immediately follow the RGB data (it's always at odd slices in the .basis file).
+ var compData = new Uint8Array(data, basisImageLevelDesc.rgbFileOfs, basisImageLevelDesc.rgbFileLen + basisImageLevelDesc.alphaFileLen);
+
+ // Decompress the palettes. This only has to be done once for each .basis file.
+ var status = etc1s_transcoder.decodePalettes(basisFileDesc.numEndpoints, endpointPalette, basisFileDesc.numSelectors, selectorPalette);
+ if (status)
+ {
+ // Decompress the Huffman tables. This only has to be done once for each .basis file.
+ status = etc1s_transcoder.decodeTables(tables);
+ if (status)
+ {
+ // Now transcode the image using the container independent transcode API. This API does not interpret any .basis file structures - only the compressed ETC1S data.
+ status = etc1s_transcoder.transcodeImage(
+ format,
+ dst, dstSize / bytesPerBlockOrPixel,
+ compData,
+ basisImageDesc.numBlocksX, basisImageDesc.numBlocksY, basisImageDesc.origWidth, basisImageDesc.origHeight, level_index,
+ 0, basisImageLevelDesc.rgbFileLen, basisFileDesc.hasAlphaSlices ? basisImageLevelDesc.rgbFileLen : 0, basisImageLevelDesc.alphaFileLen,
+ 0,
+ basisFileDesc.hasAlphaSlices,
+ basisFileDesc.isVideo,
+ 0,
+ 0);
+
+ if (!status)
+ log('transcodeImage() failed');
+ }
+ else
+ {
+ log('decodeTables() failed');
+ }
+ }
+ else
+ {
+ log('decodePalettes() failed');
+ }
+
+ etc1s_transcoder.delete();
+
+ if (!status)
+ {
+ log('etc1s_transcoder failed');
+ console.warn('etc1s_transcoder failed');
+ basisFile.close();
+ basisFile.delete();
+ return;
+ }
+ else
+ {
+ log('Successfully called etc1s_transcoder.transcodeImage()');
+ }
+ }
+ else
+ {
+ // Create a Uint8Array pointing to the image's compressed data.
+ var compData = new Uint8Array(data, basisImageLevelDesc.rgbFileOfs, basisImageLevelDesc.rgbFileLen);
+
+ // Transcode the UASTC texture data to the desired output format.
+ status = Module.transcodeUASTCImage(
+ format,
+ dst, dstSize / bytesPerBlockOrPixel,
+ compData,
+ basisImageDesc.numBlocksX, basisImageDesc.numBlocksY, basisImageDesc.origWidth, basisImageDesc.origHeight, level_index,
+ 0, basisImageLevelDesc.rgbFileLen,
+ 0,
+ basisFileDesc.hasAlphaSlices,
+ basisFileDesc.isVideo,
+ 0,
+ 0,
+ -1, -1);
+
+ if (!status)
+ {
+ log('transcodeUASTCImage() failed');
+ console.warn('transcodeUASTCImage() failed');
+ basisFile.close();
+ basisFile.delete();
+ return;
+ }
+ else
+ {
+ log('Successfully called transcodeUASTCImage()');
+ }
+ }
+ }
+ else
+ {
+ // Use the high-level transcode API, which requires a .basis file.
+ if (!basisFile.transcodeImage(dst, 0, 0, format, 0, 0)) {
+ log('basisFile.transcodeImage failed');
+ console.warn('transcodeImage failed');
+ basisFile.close();
+ basisFile.delete();
+
+ return;
+ }
}
const elapsed = performance.now() - startTime;
@@ -347,13 +538,18 @@ function viewAlpha() { drawMode = 2; redraw(); }
.basis file:
-
+
+
+
+
+ Use Container Independent Transcoding API's:
+
diff --git a/webgl/transcoder/CMakeLists.txt b/webgl/transcoder/CMakeLists.txt
index 2216c53..70f963b 100644
--- a/webgl/transcoder/CMakeLists.txt
+++ b/webgl/transcoder/CMakeLists.txt
@@ -10,8 +10,8 @@ if (EMSCRIPTEN)
basis_wrappers.cpp
)
- target_compile_definitions(basis_transcoder.js PRIVATE NDEBUG BASISD_SUPPORT_UASTC=1 BASISD_SUPPORT_BC7=1 BASISD_SUPPORT_ATC=0 BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY=0 BASISD_SUPPORT_PVRTC2=0 BASISD_SUPPORT_FXT1=0 BASISD_SUPPORT_ETC2_EAC_RG11=0)
- target_compile_options(basis_transcoder.js PRIVATE -O3)
+ target_compile_definitions(basis_transcoder.js PRIVATE NDEBUG BASISD_SUPPORT_UASTC=1 BASISD_SUPPORT_BC7=1 BASISD_SUPPORT_ATC=0 BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY=0 BASISD_SUPPORT_PVRTC2=0 BASISD_SUPPORT_FXT1=0 BASISD_SUPPORT_ETC2_EAC_RG11=0 BASISU_SUPPORT_ENCODING=0)
+ target_compile_options(basis_transcoder.js PRIVATE -O3 -fno-strict-aliasing)
target_include_directories(basis_transcoder.js PRIVATE ../../transcoder)
set_target_properties(basis_transcoder.js PROPERTIES
diff --git a/webgl/transcoder/basis_wrappers.cpp b/webgl/transcoder/basis_wrappers.cpp
index a6cbffe..8056b0d 100644
--- a/webgl/transcoder/basis_wrappers.cpp
+++ b/webgl/transcoder/basis_wrappers.cpp
@@ -1,244 +1,951 @@
-// basis_wrappers.cpp - Simple C-style wrappers to the C++ transcoder for WebGL use.
+// basis_wrappers.cpp - Wrappers to the C++ compressor and transcoder for WebAssembly/WebGL use.
+//
+// Important:
+// Compile with -fno-strict-aliasing
+// The "initializeBasis()" function MUST be called at least once before using either the compressor or transcoder.
+//
+// There are four main categories of wrappers in this module:
+// 1. Transcoding, low-level .basis file information: See class basis_file. Only depends on transcoder/basisu_transcoder.cpp.
+// getFileDesc(), getImageDesc(), getImageLevelDesc(): These functions return low-level information about where compressed data is located for each image in a .basis file.
+// This is useful for when you want to extract the compressed data and embed it into your own file formats, for container independent transcoding.
+//
+// 2. Encoding (optional): See class basis_encoder. Encodes PNG or 32bpp images to .basis files in memory. Must compile with BASISU_SUPPORT_ENCODING=1.
+// Requires basisu_transcoder.cpp as well as all the .cpp files in the "encoder" directory. Results in a larger WebAssembly executable.
+//
+// 3. Low level transcoding/container independent transcoding: See class lowlevel_etc1s_image_transcoder or function transcodeUASTCImage(). For
+// transcoding raw compressed ETC1S/UASTC texture data from non-.basis files (say from KTX2) to GPU texture data.
+//
+// 4. Helpers, transcoder texture format information: See functions getBytesPerBlockOrPixel(), formatHasAlpha(), etc.
+
+// If BASISU_SUPPORT_ENCODING is 1, wrappers for the compressor will be included. Otherwise, only the wrappers for the transcoder will be compiled in.
+#ifndef BASISU_SUPPORT_ENCODING
+#define BASISU_SUPPORT_ENCODING 0
+#endif
+
+// Enable debug printf()'s in this module.
+#ifndef BASISU_DEBUG_PRINTF
+#define BASISU_DEBUG_PRINTF 0
+#endif
+
#include "basisu_transcoder.h"
#include
#include
+#if BASISU_SUPPORT_ENCODING
+#include "../../encoder/basisu_comp.h"
+#include "../../encoder/basisu_resampler_filters.h"
+#endif
+
using namespace emscripten;
using namespace basist;
+using namespace basisu;
-static basist::etc1_global_selector_codebook *g_pGlobal_codebook;
+static basist::etc1_global_selector_codebook* g_pGlobal_codebook;
void basis_init()
{
- basisu_transcoder_init();
+#if BASISU_DEBUG_PRINTF
+ printf("basis_init()\n");
+#endif
- if (!g_pGlobal_codebook)
- g_pGlobal_codebook = new basist::etc1_global_selector_codebook(g_global_selector_cb_size, g_global_selector_cb);
+ if (g_pGlobal_codebook)
+ return;
+
+#if BASISU_SUPPORT_ENCODING
+ basisu_encoder_init();
+#endif
+
+ basisu_transcoder_init();
+
+ g_pGlobal_codebook = new basist::etc1_global_selector_codebook(g_global_selector_cb_size, g_global_selector_cb);
+}
+
+static void copy_from_jsbuffer(const emscripten::val& srcBuffer, std::vector& dstVec)
+{
+ unsigned int length = srcBuffer["length"].as();
+
+ dstVec.resize(length);
+
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = srcBuffer["constructor"].new_(memory, reinterpret_cast(dstVec.data()), length);
+
+ // Copy the bytes from the Javascript buffer.
+ memoryView.call("set", srcBuffer);
+}
+
+static bool copy_to_jsbuffer(const emscripten::val& dstBuffer, const std::vector& srcVec)
+{
+ if (srcVec.empty())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("copy_to_jsbuffer: Provided source buffer is empty\n");
+#endif
+ return false;
+ }
+
+ // Make sure the provided buffer from Javascript is big enough. If not, bail.
+ int dstBufferLen = dstBuffer["byteLength"].as();
+
+ if (srcVec.size() > dstBufferLen)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("copy_to_jsbuffer: Provided destination buffer is too small (wanted %u bytes, got %u bytes)!\n", (uint32_t)srcVec.size(), dstBufferLen);
+#endif
+ assert(0);
+ return false;
+ }
+
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(srcVec.data()), srcVec.size());
+
+ // Copy the bytes into the Javascript buffer.
+ dstBuffer.call("set", memoryView);
+
+ return true;
}
#define MAGIC 0xDEADBEE1
-struct basis_file
+struct basis_file_desc
{
- int m_magic = 0;
- basisu_transcoder m_transcoder;
- std::vector m_file;
+ uint32_t m_version;
+
+ uint32_t m_us_per_frame;
+
+ uint32_t m_total_images;
+
+ uint32_t m_userdata0;
+ uint32_t m_userdata1;
+
+ // Type of texture (cETC1S or cUASTC4x4)
+ uint32_t m_tex_format; // basis_tex_format
+
+ bool m_y_flipped;
+ bool m_has_alpha_slices;
+
+ // ETC1S endpoint codebook
+ uint32_t m_num_endpoints;
+ uint32_t m_endpoint_palette_ofs;
+ uint32_t m_endpoint_palette_len;
- basis_file(const emscripten::val& jsBuffer)
- : m_file([&]() {
- size_t byteLength = jsBuffer["byteLength"].as();
- return std::vector(byteLength);
- }()),
- m_transcoder(g_pGlobal_codebook)
- {
- unsigned int length = jsBuffer["length"].as();
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
- memoryView.call("set", jsBuffer);
+ // ETC1S selector codebook
+ uint32_t m_num_selectors;
+ uint32_t m_selector_palette_ofs;
+ uint32_t m_selector_palette_len;
- if (!m_transcoder.validate_header(m_file.data(), m_file.size())) {
- m_file.clear();
- }
-
- // Initialized after validation
- m_magic = MAGIC;
- }
-
- void close() {
- assert(m_magic == MAGIC);
- m_file.clear();
- }
-
- uint32_t getHasAlpha() {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- basisu_image_level_info li;
- if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), li, 0, 0))
- return 0;
-
- return li.m_alpha_flag;
- }
-
- uint32_t getNumImages() {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- return m_transcoder.get_total_images(m_file.data(), m_file.size());
- }
-
- uint32_t getNumLevels(uint32_t image_index) {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- basisu_image_info ii;
- if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), ii, image_index))
- return 0;
-
- return ii.m_total_levels;
- }
-
- uint32_t getImageWidth(uint32_t image_index, uint32_t level_index) {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
-
- return orig_width;
- }
-
- uint32_t getImageHeight(uint32_t image_index, uint32_t level_index) {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
-
- return orig_height;
- }
-
- uint32_t getImageTranscodedSizeInBytes(uint32_t image_index, uint32_t level_index, uint32_t format) {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
-
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
-
- const transcoder_texture_format transcoder_format = static_cast(format);
-
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- // Uncompressed formats are just plain raster images.
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
- return bytes_per_slice;
- }
- else
- {
- // Compressed formats are 2D arrays of blocks.
- const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
-
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- return size_in_bytes;
- }
-
- return total_blocks * bytes_per_block;
- }
- }
-
- bool isUASTC() {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return false;
-
- return m_transcoder.get_tex_format(m_file.data(), m_file.size()) == basis_tex_format::cUASTC4x4;
- }
-
- uint32_t startTranscoding() {
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- return m_transcoder.start_transcoding(m_file.data(), m_file.size());
- }
-
- uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t unused, uint32_t get_alpha_for_opaque_formats) {
- (void)unused;
-
- assert(m_magic == MAGIC);
- if (m_magic != MAGIC)
- return 0;
-
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
-
- const transcoder_texture_format transcoder_format = static_cast(format);
-
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
-
- std::vector dst_data;
-
- uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
-
- uint32_t status;
-
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
-
- dst_data.resize(bytes_per_slice);
-
- status = m_transcoder.transcode_image_level(
- m_file.data(), m_file.size(), image_index, level_index,
- dst_data.data(), orig_width * orig_height,
- transcoder_format,
- flags,
- orig_width,
- nullptr,
- orig_height);
- }
- else
- {
- uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
-
- uint32_t required_size = total_blocks * bytes_per_block;
-
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- // The transcoder will clear the extra bytes followed the used blocks to 0.
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- assert(required_size >= total_blocks * bytes_per_block);
- }
-
- dst_data.resize(required_size);
-
- status = m_transcoder.transcode_image_level(
- m_file.data(), m_file.size(), image_index, level_index,
- dst_data.data(), dst_data.size() / bytes_per_block,
- static_cast(format),
- flags);
- }
-
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
-
- dst.call("set", memoryView);
- return status;
- }
+ // Huffman codelength tables
+ uint32_t m_tables_ofs;
+ uint32_t m_tables_len;
};
-EMSCRIPTEN_BINDINGS(basis_transcoder) {
+struct basis_image_desc
+{
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+ uint32_t m_num_levels;
+ // Will be true if the image has alpha (for UASTC this may vary per-image)
+ bool m_alpha_flag;
+ bool m_iframe_flag;
+};
+
+struct basis_image_level_desc
+{
+ // File offset/length of the compressed ETC1S or UASTC texture data.
+ uint32_t m_rgb_file_ofs;
+ uint32_t m_rgb_file_len;
+
+ // Optional alpha data file offset/length - will be 0's for UASTC or opaque ETC1S files.
+ uint32_t m_alpha_file_ofs;
+ uint32_t m_alpha_file_len;
+};
+
+struct basis_file
+{
+ int m_magic = 0;
+ basisu_transcoder m_transcoder;
+ std::vector m_file;
+
+ basis_file(const emscripten::val& jsBuffer)
+ : m_file([&]() {
+ size_t byteLength = jsBuffer["byteLength"].as();
+ return std::vector(byteLength);
+ }()),
+ m_transcoder(g_pGlobal_codebook)
+ {
+ if (!g_pGlobal_codebook)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_file::basis_file: Must call basis_init() first!\n");
+#endif
+ assert(0);
+ return;
+ }
+
+ unsigned int length = jsBuffer["length"].as();
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
+ memoryView.call("set", jsBuffer);
+
+ if (!m_transcoder.validate_header(m_file.data(), m_file.size())) {
+ m_file.clear();
+ }
+
+ // Initialized after validation
+ m_magic = MAGIC;
+ }
+
+ void close() {
+ assert(m_magic == MAGIC);
+ m_file.clear();
+ }
+
+ uint32_t getHasAlpha() {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ basisu_image_level_info li;
+ if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), li, 0, 0))
+ return 0;
+
+ return li.m_alpha_flag;
+ }
+
+ uint32_t getNumImages() {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ return m_transcoder.get_total_images(m_file.data(), m_file.size());
+ }
+
+ uint32_t getNumLevels(uint32_t image_index) {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ basisu_image_info ii;
+ if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), ii, image_index))
+ return 0;
+
+ return ii.m_total_levels;
+ }
+
+ uint32_t getImageWidth(uint32_t image_index, uint32_t level_index) {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
+
+ return orig_width;
+ }
+
+ uint32_t getImageHeight(uint32_t image_index, uint32_t level_index) {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
+
+ return orig_height;
+ }
+
+ basis_file_desc getFileDesc() {
+ basis_file_desc result;
+ memset(&result, 0, sizeof(result));
+
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return result;
+
+ basisu_file_info file_info;
+
+ if (!m_transcoder.get_file_info(m_file.data(), m_file.size(), file_info))
+ {
+ assert(0);
+ return result;
+ }
+
+ result.m_version = file_info.m_version;
+ result.m_us_per_frame = file_info.m_us_per_frame;
+ result.m_total_images = file_info.m_total_images;
+ result.m_userdata0 = file_info.m_userdata0;
+ result.m_userdata1 = file_info.m_userdata1;
+ result.m_tex_format = static_cast(file_info.m_tex_format);
+ result.m_y_flipped = file_info.m_y_flipped;
+ result.m_has_alpha_slices = file_info.m_has_alpha_slices;
+
+ result.m_num_endpoints = file_info.m_total_endpoints;
+ result.m_endpoint_palette_ofs = file_info.m_endpoint_codebook_ofs;
+ result.m_endpoint_palette_len = file_info.m_endpoint_codebook_size;
+
+ result.m_num_selectors = file_info.m_total_selectors;
+ result.m_selector_palette_ofs = file_info.m_selector_codebook_ofs;
+ result.m_selector_palette_len = file_info.m_selector_codebook_size;
+
+ result.m_tables_ofs = file_info.m_tables_ofs;
+ result.m_tables_len = file_info.m_tables_size;
+
+ return result;
+ }
+
+ basis_image_desc getImageDesc(uint32_t image_index) {
+ basis_image_desc result;
+ memset(&result, 0, sizeof(result));
+
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return result;
+
+ basisu_image_info image_info;
+
+ // bool get_image_info(const void *pData, uint32_t data_size, basisu_image_info &image_info, uint32_t image_index) const;
+ if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), image_info, image_index))
+ {
+ assert(0);
+ return result;
+ }
+
+ result.m_orig_width = image_info.m_orig_width;
+ result.m_orig_height = image_info.m_orig_height;
+ result.m_num_blocks_x = image_info.m_num_blocks_x;
+ result.m_num_blocks_y = image_info.m_num_blocks_y;
+ result.m_num_levels = image_info.m_total_levels;
+ result.m_alpha_flag = image_info.m_alpha_flag;
+ result.m_iframe_flag = image_info.m_iframe_flag;
+
+ return result;
+ }
+
+ basis_image_level_desc getImageLevelDesc(uint32_t image_index, uint32_t level_index) {
+ basis_image_level_desc result;
+ memset(&result, 0, sizeof(result));
+
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return result;
+
+ basisu_image_level_info image_info;
+
+ if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), image_info, image_index, level_index))
+ {
+ assert(0);
+ return result;
+ }
+
+ result.m_rgb_file_ofs = image_info.m_rgb_file_ofs;
+ result.m_rgb_file_len = image_info.m_rgb_file_len;
+ result.m_alpha_file_ofs = image_info.m_alpha_file_ofs;
+ result.m_alpha_file_len = image_info.m_alpha_file_len;
+
+ return result;
+ }
+
+ uint32_t getImageTranscodedSizeInBytes(uint32_t image_index, uint32_t level_index, uint32_t format) {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
+
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
+
+ const transcoder_texture_format transcoder_format = static_cast(format);
+
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ // Uncompressed formats are just plain raster images.
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+ return bytes_per_slice;
+ }
+ else
+ {
+ // Compressed formats are 2D arrays of blocks.
+ const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ return size_in_bytes;
+ }
+
+ return total_blocks * bytes_per_block;
+ }
+ }
+
+ bool isUASTC() {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return false;
+
+ return m_transcoder.get_tex_format(m_file.data(), m_file.size()) == basis_tex_format::cUASTC4x4;
+ }
+
+ uint32_t startTranscoding() {
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ return m_transcoder.start_transcoding(m_file.data(), m_file.size());
+ }
+
+ uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t unused, uint32_t get_alpha_for_opaque_formats) {
+ (void)unused;
+
+ assert(m_magic == MAGIC);
+ if (m_magic != MAGIC)
+ return 0;
+
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
+
+ const transcoder_texture_format transcoder_format = static_cast(format);
+
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
+
+ std::vector dst_data;
+
+ uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
+
+ uint32_t status;
+
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+
+ dst_data.resize(bytes_per_slice);
+
+ status = m_transcoder.transcode_image_level(
+ m_file.data(), m_file.size(), image_index, level_index,
+ dst_data.data(), orig_width * orig_height,
+ transcoder_format,
+ flags,
+ orig_width,
+ nullptr,
+ orig_height);
+ }
+ else
+ {
+ uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+
+ uint32_t required_size = total_blocks * bytes_per_block;
+
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ // The transcoder will clear the extra bytes followed the used blocks to 0.
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ assert(required_size >= total_blocks * bytes_per_block);
+ }
+
+ dst_data.resize(required_size);
+
+ status = m_transcoder.transcode_image_level(
+ m_file.data(), m_file.size(), image_index, level_index,
+ dst_data.data(), dst_data.size() / bytes_per_block,
+ static_cast(format),
+ flags);
+ }
+
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
+
+ dst.call("set", memoryView);
+ return status;
+ }
+};
+
+#if BASISU_SUPPORT_ENCODING
+class basis_encoder
+{
+public:
+ basis_compressor_params m_params;
+
+ basis_encoder()
+ {
+ }
+
+ bool set_slice_source_image(uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t src_image_width, uint32_t src_image_height, bool src_image_is_png)
+ {
+ // Resize the source_images array if necessary
+ if (slice_index >= m_params.m_source_images.size())
+ m_params.m_source_images.resize(slice_index + 1);
+
+ // First copy the src image buffer to the heap.
+ std::vector src_image_buf;
+ copy_from_jsbuffer(src_image_js_val, src_image_buf);
+
+ // Now extract the source image.
+ image& src_img = m_params.m_source_images[slice_index];
+ if (src_image_is_png)
+ {
+ // It's a PNG file, so try and parse it.
+ if (!load_png(src_image_buf.data(), src_image_buf.size(), src_img, nullptr))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_encoder::set_slice_source_image: Failed parsing provided PNG file!\n");
+#endif
+ return false;
+ }
+
+ src_image_width = src_img.get_width();
+ src_image_height = src_img.get_height();
+ }
+ else
+ {
+ // It's a raw image, so check the buffer's size.
+ if (src_image_buf.size() != src_image_width * src_image_height * sizeof(uint32_t))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_encoder::set_slice_source_image: Provided source buffer has an invalid size!\n");
+#endif
+ return false;
+ }
+
+ // Copy the raw image's data into our source image.
+ src_img.resize(src_image_width, src_image_height);
+ memcpy(src_img.get_ptr(), src_image_buf.data(), src_image_width * src_image_height * sizeof(uint32_t));
+ }
+
+ return true;
+ }
+
+ uint32_t encode(const emscripten::val& dst_basis_file_js_val)
+ {
+ if (!g_pGlobal_codebook)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_encoder::encode: Must call basis_init() first!\n");
+#endif
+ assert(0);
+ return 0;
+ }
+
+ basist::etc1_global_selector_codebook sel_codebook(basist::g_global_selector_cb_size, basist::g_global_selector_cb);
+
+ // We don't use threading for now, but the compressor needs a job pool.
+ job_pool jpool(1);
+
+ // Initialize the compression parameters structure. This is the same structure that the command line tool fills in.
+ basis_compressor_params ¶ms = m_params;
+
+ params.m_pJob_pool = &jpool;
+
+ // Disabling multithreading for now, which sucks.
+ params.m_multithreading = false;
+
+ params.m_status_output = params.m_debug;
+
+ params.m_read_source_images = false;
+ params.m_write_output_basis_files = false;
+ params.m_pSel_codebook = &sel_codebook;
+
+ basis_compressor comp;
+
+ if (!comp.init(params))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("Failed initializing BasisU compressor! One or more provided parameters may be invalid.\n");
+#endif
+ return 0;
+ }
+
+#if BASISU_DEBUG_PRINTF
+ printf("Begin BasisU compression\n");
+#endif
+
+ basis_compressor::error_code ec = comp.process();
+
+#if BASISU_DEBUG_PRINTF
+ printf("BasisU compression done, status %u, %u bytes\n", (uint32_t)ec, (uint32_t)comp.get_output_basis_file().size());
+#endif
+
+ if (ec != basis_compressor::cECSuccess)
+ {
+ // Something failed during compression.
+#if BASISU_DEBUG_PRINTF
+ printf("BasisU compression failed with status %u!\n", (uint32_t)ec);
+#endif
+ return 0;
+ }
+
+ // Compression succeeded, so copy the .basis file bytes to the caller's buffer.
+ if (!copy_to_jsbuffer(dst_basis_file_js_val, comp.get_output_basis_file()))
+ return 0;
+
+ // Return the file size of the .basis file in bytes.
+ return (uint32_t)comp.get_output_basis_file().size();
+ }
+};
+#endif
+
+class lowlevel_etc1s_image_transcoder : public basisu_lowlevel_etc1s_transcoder
+{
+ // Using our own transcoder state, for video support.
+ basisu_transcoder_state m_state;
+
+public:
+ lowlevel_etc1s_image_transcoder() :
+ basisu_lowlevel_etc1s_transcoder(g_pGlobal_codebook)
+ {
+ }
+
+ bool decode_palettes(uint32_t num_endpoints, const emscripten::val& endpoint_data, uint32_t num_selectors, const emscripten::val& selector_data)
+ {
+ std::vector temp_endpoint_data, temp_selector_data;
+ copy_from_jsbuffer(endpoint_data, temp_endpoint_data);
+ copy_from_jsbuffer(selector_data, temp_selector_data);
+
+#if 0
+ printf("decode_palettes: %u %u %u %u, %u %u\n",
+ num_endpoints, (uint32_t)temp_endpoint_data.size(),
+ num_selectors, (uint32_t)temp_selector_data.size(),
+ temp_endpoint_data[0], temp_selector_data[0]);
+#endif
+
+ if (!temp_endpoint_data.size() || !temp_selector_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("decode_tables: endpoint_data and/or selector_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ return basisu_lowlevel_etc1s_transcoder::decode_palettes(num_endpoints, &temp_endpoint_data[0], (uint32_t)temp_endpoint_data.size(),
+ num_selectors, &temp_selector_data[0], (uint32_t)temp_selector_data.size());
+ }
+
+ bool decode_tables(const emscripten::val& table_data)
+ {
+ std::vector temp_table_data;
+ copy_from_jsbuffer(table_data, temp_table_data);
+
+ if (!temp_table_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("decode_tables: table_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ return basisu_lowlevel_etc1s_transcoder::decode_tables(&temp_table_data[0], (uint32_t)temp_table_data.size());
+ }
+
+ bool transcode_image(
+ uint32_t target_format, // see transcoder_texture_format
+ const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ const emscripten::val& compressed_data,
+ uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
+ uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length,
+ uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
+ bool basis_file_has_alpha_slices,
+ bool is_video,
+ uint32_t output_row_pitch_in_blocks_or_pixels,
+ uint32_t output_rows_in_pixels)
+ {
+ if (!g_pGlobal_codebook)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: basis_init() must be called first\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ // FIXME: Access the JavaScript buffer directly vs. copying it.
+ std::vector temp_comp_data;
+ copy_from_jsbuffer(compressed_data, temp_comp_data);
+
+ if (!temp_comp_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: compressed_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ uint32_t output_blocks_len = output_blocks["byteLength"].as();
+ if (!output_blocks_len)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: output_blocks is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ std::vector temp_output_blocks(output_blocks_len);
+
+ bool status = basisu_lowlevel_etc1s_transcoder::transcode_image(
+ (transcoder_texture_format)target_format,
+ &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
+ &temp_comp_data[0], temp_comp_data.size(),
+ num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
+ rgb_offset, rgb_length, alpha_offset, alpha_length,
+ decode_flags,
+ basis_file_has_alpha_slices,
+ is_video,
+ output_row_pitch_in_blocks_or_pixels,
+ &m_state,
+ output_rows_in_pixels);
+
+ if (!status)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: basisu_lowlevel_etc1s_transcoder::transcode_image failed\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
+ return false;
+
+ return true;
+ }
+};
+
+bool transcode_uastc_image(
+ uint32_t target_format_int, // see transcoder_texture_format
+ const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ const emscripten::val& compressed_data,
+ uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
+ uint32_t slice_offset, uint32_t slice_length,
+ uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
+ bool has_alpha,
+ bool is_video,
+ uint32_t output_row_pitch_in_blocks_or_pixels,
+ uint32_t output_rows_in_pixels,
+ int channel0, int channel1)
+{
+ transcoder_texture_format target_format = static_cast(target_format_int);
+
+ if (!g_pGlobal_codebook)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: basis_init() must be called first\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ // FIXME: Access the JavaScript buffer directly vs. copying it.
+ std::vector temp_comp_data;
+ copy_from_jsbuffer(compressed_data, temp_comp_data);
+
+ if (!temp_comp_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: compressed_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ uint32_t output_blocks_len = output_blocks["byteLength"].as();
+ if (!output_blocks_len)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: output_blocks is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+#if 0
+ printf("format: %u\n", (uint32_t)target_format);
+ printf("output_blocks size: %u buf size: %u\n", output_blocks_len, output_blocks_buf_size_in_blocks_or_pixels);
+ printf("compressed_data size: %u\n", compressed_data["byteLength"].as());
+ printf("%u %u %u %u %u\n", num_blocks_x, num_blocks_y, orig_width, orig_height, level_index);
+ printf("%u %u\n", slice_offset, slice_length);
+ printf("%u\n", decode_flags);
+ printf("has_alpha: %u is_video: %u\n", has_alpha, is_video);
+#endif
+
+ std::vector temp_output_blocks(output_blocks_len);
+
+ basisu_lowlevel_uastc_transcoder transcoder;
+
+ bool status = transcoder.transcode_image(
+ (transcoder_texture_format)target_format,
+ &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
+ &temp_comp_data[0], temp_comp_data.size(),
+ num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
+ slice_offset, slice_length,
+ decode_flags,
+ has_alpha,
+ is_video,
+ output_row_pitch_in_blocks_or_pixels,
+ nullptr,
+ output_rows_in_pixels,
+ channel0, channel1);
+
+ if (!status)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: basisu_lowlevel_uastc_transcoder::transcode_image failed\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
+ return false;
+
+ return true;
+}
+
+uint32_t get_bytes_per_block_or_pixel(uint32_t transcoder_tex_fmt)
+{
+ return basis_get_bytes_per_block_or_pixel(static_cast(transcoder_tex_fmt));
+}
+
+bool format_has_alpha(uint32_t transcoder_tex_fmt)
+{
+ return basis_transcoder_format_has_alpha(static_cast(transcoder_tex_fmt));
+}
+
+bool format_is_uncompressed(uint32_t transcoder_tex_fmt)
+{
+ return basis_transcoder_format_is_uncompressed(static_cast(transcoder_tex_fmt));
+}
+
+bool is_format_supported(uint32_t transcoder_tex_fmt)
+{
+ return basis_is_format_supported(static_cast(transcoder_tex_fmt));
+}
+
+uint32_t get_format_block_width(uint32_t transcoder_tex_fmt)
+{
+ return basis_get_block_width(static_cast(transcoder_tex_fmt));
+}
+
+uint32_t get_format_block_height(uint32_t transcoder_tex_fmt)
+{
+ return basis_get_block_height(static_cast(transcoder_tex_fmt));
+}
+
+EMSCRIPTEN_BINDINGS(basis_codec) {
function("initializeBasis", &basis_init);
+ // Expose BasisFileDesc structure
+ value_object("BasisFileDesc")
+ .field("version", &basis_file_desc::m_version)
+ .field("usPerFrame", &basis_file_desc::m_us_per_frame)
+ .field("totalImages", &basis_file_desc::m_total_images)
+ .field("userdata0", &basis_file_desc::m_userdata0)
+ .field("userdata1", &basis_file_desc::m_userdata1)
+ .field("texFormat", &basis_file_desc::m_tex_format)
+ .field("yFlipped", &basis_file_desc::m_y_flipped)
+ .field("hasAlphaSlices", &basis_file_desc::m_has_alpha_slices)
+ .field("numEndpoints", &basis_file_desc::m_num_endpoints)
+ .field("endpointPaletteOfs", &basis_file_desc::m_endpoint_palette_ofs)
+ .field("endpointPaletteLen", &basis_file_desc::m_endpoint_palette_len)
+ .field("numSelectors", &basis_file_desc::m_num_selectors)
+ .field("selectorPaletteOfs", &basis_file_desc::m_selector_palette_ofs)
+ .field("selectorPaletteLen", &basis_file_desc::m_selector_palette_len)
+ .field("tablesOfs", &basis_file_desc::m_tables_ofs)
+ .field("tablesLen", &basis_file_desc::m_tables_len)
+ ;
+
+ // Expose BasisImageDesc structure
+ value_object("BasisImageDesc")
+ .field("origWidth", &basis_image_desc::m_orig_width)
+ .field("origHeight", &basis_image_desc::m_orig_height)
+ .field("numBlocksX", &basis_image_desc::m_num_blocks_x)
+ .field("numBlocksY", &basis_image_desc::m_num_blocks_y)
+ .field("numLevels", &basis_image_desc::m_num_levels)
+ .field("alphaFlag", &basis_image_desc::m_alpha_flag)
+ .field("iframeFlag", &basis_image_desc::m_iframe_flag)
+ ;
+
+ // Expose BasisImageLevelDesc structure
+ value_object("BasisImageLevelDesc")
+ .field("rgbFileOfs", &basis_image_level_desc::m_rgb_file_ofs)
+ .field("rgbFileLen", &basis_image_level_desc::m_rgb_file_len)
+ .field("alphaFileOfs", &basis_image_level_desc::m_alpha_file_ofs)
+ .field("alphaFileLen", &basis_image_level_desc::m_alpha_file_len)
+ ;
+
+ // Expose some key enums to JavaScript code.
+
+ // enum class transcoder_texture_format
+ enum_("transcoder_texture_format")
+ .value("cTFETC1_RGB", transcoder_texture_format::cTFETC1_RGB)
+ .value("cTFETC2_RGBA", transcoder_texture_format::cTFETC2_RGBA)
+ .value("cTFBC1_RGB", transcoder_texture_format::cTFBC1_RGB)
+ .value("cTFBC3_RGBA", transcoder_texture_format::cTFBC3_RGBA)
+ .value("cTFBC4_R", transcoder_texture_format::cTFBC4_R)
+ .value("cTFBC5_RG", transcoder_texture_format::cTFBC5_RG)
+ .value("cTFBC7_RGBA", transcoder_texture_format::cTFBC7_RGBA)
+ .value("cTFPVRTC1_4_RGB", transcoder_texture_format::cTFPVRTC1_4_RGB)
+ .value("cTFPVRTC1_4_RGBA", transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ .value("cTFASTC_4x4_RGBA", transcoder_texture_format::cTFASTC_4x4_RGBA)
+ .value("cTFATC_RGB", transcoder_texture_format::cTFATC_RGB)
+ .value("cTFATC_RGBA", transcoder_texture_format::cTFATC_RGBA)
+ .value("cTFFXT1_RGB", transcoder_texture_format::cTFFXT1_RGB)
+ .value("cTFPVRTC2_4_RGB", transcoder_texture_format::cTFPVRTC2_4_RGB)
+ .value("cTFPVRTC2_4_RGBA", transcoder_texture_format::cTFPVRTC2_4_RGBA)
+ .value("cTFETC2_EAC_R11", transcoder_texture_format::cTFETC2_EAC_R11)
+ .value("cTFETC2_EAC_RG11", transcoder_texture_format::cTFETC2_EAC_RG11)
+ .value("cTFRGBA32", transcoder_texture_format::cTFRGBA32)
+ .value("cTFRGB565", transcoder_texture_format::cTFRGB565)
+ .value("cTFBGR565", transcoder_texture_format::cTFBGR565)
+ .value("cTFRGBA4444", transcoder_texture_format::cTFRGBA4444)
+ .value("cTFTotalTextureFormats", transcoder_texture_format::cTFTotalTextureFormats)
+ ;
+
+ // Expose some useful transcoder_texture_format helper functions
+ function("getBytesPerBlockOrPixel", &get_bytes_per_block_or_pixel);
+ function("formatHasAlpha", &format_has_alpha);
+ function("formatIsUncompressed", &format_is_uncompressed);
+ function("isFormatSupported", &is_format_supported);
+ function("getFormatBlockWidth", &get_format_block_width);
+ function("getFormatBlockHeight", &get_format_block_height);
+
+ // Expose enum basis_texture_type
+ enum_("basis_texture_type")
+ .value("cBASISTexType2D", cBASISTexType2D)
+ .value("cBASISTexType2DArray", cBASISTexType2DArray)
+ .value("cBASISTexTypeCubemapArray", cBASISTexTypeCubemapArray)
+ .value("cBASISTexTypeVideoFrames", cBASISTexTypeVideoFrames)
+ .value("cBASISTexTypeVolume", cBASISTexTypeVolume)
+ ;
+
+ // Expose enum basis_tex_format
+ enum_("basis_tex_format")
+ .value("cETC1S", basis_tex_format::cETC1S)
+ .value("cUASTC4x4", basis_tex_format::cUASTC4x4)
+ ;
+
+ // Transcoder object. If all you want to do is transcode already encoded .basis files, this is all you really need.
class_("BasisFile")
.constructor()
.function("close", optional_override([](basis_file& self) {
@@ -262,15 +969,326 @@ EMSCRIPTEN_BINDINGS(basis_transcoder) {
.function("getImageHeight", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex) {
return self.getImageHeight(imageIndex, levelIndex);
}))
+ // format is enum class transcoder_texture_format
.function("getImageTranscodedSizeInBytes", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex, uint32_t format) {
return self.getImageTranscodedSizeInBytes(imageIndex, levelIndex, format);
}))
.function("startTranscoding", optional_override([](basis_file& self) {
return self.startTranscoding();
}))
+ // format is enum class transcoder_texture_format
.function("transcodeImage", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t levelIndex, uint32_t format, uint32_t unused, uint32_t getAlphaForOpaqueFormats) {
return self.transcodeImage(dst, imageIndex, levelIndex, format, unused, getAlphaForOpaqueFormats);
}))
- ;
+ // Returns low-level information about the basis file.
+ .function("getFileDesc", optional_override([](basis_file& self) {
+ return self.getFileDesc();
+ }))
+ // Returns low-level information about a specific image in a basis file. An image can contain 1 or more mipmap levels.
+ .function("getImageDesc", optional_override([](basis_file& self, uint32_t imageIndex) {
+ return self.getImageDesc(imageIndex);
+ }))
+ // Returns low-level information about a specific image mipmap level in a basis file.
+ .function("getImageLevelDesc", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex) {
+ return self.getImageLevelDesc(imageIndex, levelIndex);
+ }))
+ ;
+
+ // Low-level container independent transcoding of ETC1S and UASTC slice data.
+ // These functions allow the caller to transcode compressed ETC1S or UASTC texture data that is embedded within arbitrary data files, such as from KTX2.
+ enum_("basisu_decode_flags")
+ .value("cDecodeFlagsPVRTCDecodeToNextPow2", cDecodeFlagsPVRTCDecodeToNextPow2)
+ .value("cDecodeFlagsTranscodeAlphaDataToOpaqueFormats", cDecodeFlagsTranscodeAlphaDataToOpaqueFormats)
+ .value("cDecodeFlagsBC1ForbidThreeColorBlocks", cDecodeFlagsBC1ForbidThreeColorBlocks)
+ .value("cDecodeFlagsOutputHasAlphaIndices", cDecodeFlagsOutputHasAlphaIndices)
+ .value("cDecodeFlagsHighQuality", cDecodeFlagsHighQuality)
+ ;
+
+ // The low-level ETC1S transcoder is a class because it has persistent state (such as the endpoint/selector codebooks and Huffman tables, and transcoder state for video)
+ class_("LowLevelETC1SImageTranscoder")
+ .constructor<>()
+ .function("decodePalettes", &lowlevel_etc1s_image_transcoder::decode_palettes)
+ .function("decodeTables", &lowlevel_etc1s_image_transcoder::decode_tables)
+ .function("transcodeImage", &lowlevel_etc1s_image_transcoder::transcode_image)
+ ;
+
+ // The low-level UASTC transcoder is a single function.
+ function("transcodeUASTCImage", &transcode_uastc_image);
+
+ // Optional encoding/compression support
+
+#if BASISU_SUPPORT_ENCODING
+
+ // Compressor Constants
+
+ constant("BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION", BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
+ constant("BASISU_DEFAULT_ENDPOINT_RDO_THRESH", BASISU_DEFAULT_ENDPOINT_RDO_THRESH);
+ constant("BASISU_DEFAULT_SELECTOR_RDO_THRESH", BASISU_DEFAULT_SELECTOR_RDO_THRESH);
+ constant("BASISU_DEFAULT_QUALITY", BASISU_DEFAULT_QUALITY);
+ constant("BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH", BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH);
+ constant("BASISU_MAX_IMAGE_DIMENSION", BASISU_MAX_IMAGE_DIMENSION);
+ constant("BASISU_QUALITY_MIN", BASISU_QUALITY_MIN);
+ constant("BASISU_QUALITY_MAX", BASISU_QUALITY_MAX);
+ constant("BASISU_MAX_ENDPOINT_CLUSTERS", BASISU_MAX_ENDPOINT_CLUSTERS);
+ constant("BASISU_MAX_SELECTOR_CLUSTERS", BASISU_MAX_SELECTOR_CLUSTERS);
+ constant("BASISU_MAX_SLICES", BASISU_MAX_SLICES);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_DEFAULT", BASISU_RDO_UASTC_DICT_SIZE_DEFAULT);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_MIN", BASISU_RDO_UASTC_DICT_SIZE_MIN);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_MAX", BASISU_RDO_UASTC_DICT_SIZE_MAX);
+ constant("BASISU_MAX_RESAMPLER_FILTERS", g_num_resample_filters);
+ constant("BASISU_DEFAULT_COMPRESSION_LEVEL", BASISU_DEFAULT_COMPRESSION_LEVEL);
+ constant("BASISU_MAX_COMPRESSION_LEVEL", BASISU_MAX_COMPRESSION_LEVEL);
+
+ constant("cPackUASTCLevelFastest", cPackUASTCLevelFastest);
+ constant("cPackUASTCLevelFaster", cPackUASTCLevelFaster);
+ constant("cPackUASTCLevelDefault", cPackUASTCLevelDefault);
+ constant("cPackUASTCLevelSlower", cPackUASTCLevelSlower);
+ constant("cPackUASTCLevelVerySlow", cPackUASTCLevelVerySlow);
+ constant("cPackUASTCLevelMask", cPackUASTCLevelMask);
+ constant("cPackUASTCFavorUASTCError", cPackUASTCFavorUASTCError);
+ constant("cPackUASTCFavorBC7Error", cPackUASTCFavorBC7Error);
+ constant("cPackUASTCETC1FasterHints", cPackUASTCETC1FasterHints);
+ constant("cPackUASTCETC1FastestHints", cPackUASTCETC1FastestHints);
+ constant("cPackUASTCETC1DisableFlipAndIndividual", cPackUASTCETC1DisableFlipAndIndividual);
+
+ constant("UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO", UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO);
+ constant("UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH", UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH);
+
+ // Compression/encoding object.
+ // You create this object, call the set() methods to fill in the parameters/source images/options, call encode(), and you get back a .basis file.
+ // You can call .encode() multiple times, changing the parameters/options in between calls.
+ class_("BasisEncoder")
+ .constructor<>()
+
+ // Compresses the provided source slice(s) to an output .basis file.
+ // At the minimum, you must provided at least 1 source slice by calling setSliceSourceImage() before calling this method.
+ .function("encode", optional_override([](basis_encoder& self, const emscripten::val& dst_basis_file_js_val) {
+ return self.encode(dst_basis_file_js_val);
+ }))
+
+ // Sets the slice's source image, either from a PNG file or from a raw 32-bit RGBA raster image.
+ // If the input is a raster image, the buffer must be width*height*4 bytes in size. The raster image is stored in top down scanline order.
+ // The first texel is the top-left texel. The texel byte order in memory is R,G,B,A (R first at offset 0, A last at offset 3).
+ // slice_index is the slice to change. Valid range is [0,BASISU_MAX_SLICES-1].
+ .function("setSliceSourceImage", optional_override([](basis_encoder& self, uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t width, uint32_t height, bool src_image_is_png) {
+ return self.set_slice_source_image(slice_index, src_image_js_val, width, height, src_image_is_png);
+ }))
+
+ // If true, the encoder will output a UASTC texture, otherwise a ETC1S texture.
+ .function("setUASTC", optional_override([](basis_encoder& self, bool uastc_flag) {
+ self.m_params.m_uastc = uastc_flag;
+ }))
+
+ // If true the source images will be Y flipped before compression.
+ .function("setYFlip", optional_override([](basis_encoder& self, bool y_flip_flag) {
+ self.m_params.m_y_flip = y_flip_flag;
+ }))
+
+ // Enables debug output to stdout
+ .function("setDebug", optional_override([](basis_encoder& self, bool debug_flag) {
+ self.m_params.m_debug = debug_flag;
+ }))
+
+ // If true, the input is assumed to be in sRGB space. Be sure to set this correctly! (Examples: True on photos, albedo/spec maps, and false on normal maps.)
+ .function("setPerceptual", optional_override([](basis_encoder& self, bool perceptual_flag) {
+ self.m_params.m_perceptual = perceptual_flag;
+ }))
+
+ // Check source images for active/used alpha channels
+ .function("setCheckForAlpha", optional_override([](basis_encoder& self, bool check_for_alpha_flag) {
+ self.m_params.m_check_for_alpha = check_for_alpha_flag;
+ }))
+
+ // Fource output .basis file to have an alpha channel
+ .function("setForceAlpha", optional_override([](basis_encoder& self, bool force_alpha_flag) {
+ self.m_params.m_force_alpha = force_alpha_flag;
+ }))
+
+ // Set source image component swizzle.
+ // r,g,b,a - valid range is [0,3]
+ .function("setSwizzle", optional_override([](basis_encoder& self, uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
+ assert((r < 4) && (g < 4) && (b < 4) && (a < 4));
+ self.m_params.m_swizzle[0] = (char)r;
+ self.m_params.m_swizzle[1] = (char)g;
+ self.m_params.m_swizzle[2] = (char)b;
+ self.m_params.m_swizzle[3] = (char)a;
+ }))
+
+ // If true, the input is assumed to be a normal map, and all source texels will be renormalized before encoding.
+ .function("setRenormalize", optional_override([](basis_encoder& self, bool renormalize_flag) {
+ self.m_params.m_renormalize = renormalize_flag;
+ }))
+
+ // Sets the max # of endpoint clusters for ETC1S mode. Use instead of setQualityLevel.
+ // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
+ .function("setMaxEndpointClusters", optional_override([](basis_encoder& self, uint32_t max_endpoint_clusters) {
+ assert(max_endpoint_clusters <= BASISU_MAX_ENDPOINT_CLUSTERS);
+ self.m_params.m_max_endpoint_clusters = max_endpoint_clusters;
+ }))
+
+ // Sets the max # of selectors clusters for ETC1S mode. Use instead of setQualityLevel.
+ // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
+ .function("setMaxSelectorClusters", optional_override([](basis_encoder& self, uint32_t max_selector_clusters) {
+ assert(max_selector_clusters <= BASISU_MAX_SELECTOR_CLUSTERS);
+ self.m_params.m_max_selector_clusters = max_selector_clusters;
+ }))
+
+ // Sets the ETC1S encoder's quality level, which controls the file size vs. quality tradeoff.
+ // Default is -1 (meaning unused - the compressor will use m_max_endpoint_clusters/m_max_selector_clusters instead to control the codebook sizes).
+ // Range is [1,BASISU_QUALITY_MAX]
+ .function("setQualityLevel", optional_override([](basis_encoder& self, int quality_level) {
+ assert(quality_level >= -1 && quality_level <= BASISU_QUALITY_MAX);
+ self.m_params.m_quality_level = quality_level;
+ }))
+
+ // The compression_level parameter controls the encoder perf vs. file size tradeoff for ETC1S files.
+ // It does not directly control file size vs. quality - see quality_level().
+ // Default is BASISU_DEFAULT_COMPRESSION_LEVEL, range is [0,BASISU_MAX_COMPRESSION_LEVEL]
+ .function("setCompressionLevel", optional_override([](basis_encoder& self, int comp_level) {
+ assert(comp_level >= 0 && comp_level <= BASISU_MAX_COMPRESSION_LEVEL);
+ self.m_params.m_compression_level = comp_level;
+ }))
+
+ // setNormalMapMode is the same as the basisu.exe "-normal_map" option. It tunes several codec parameters so compression works better on normal maps.
+ .function("setNormalMap", optional_override([](basis_encoder& self) {
+ self.m_params.m_perceptual = false;
+ self.m_params.m_mip_srgb = false;
+ self.m_params.m_no_selector_rdo = true;
+ self.m_params.m_no_endpoint_rdo = true;
+ }))
+
+ // Sets selector RDO threshold
+ // Default is BASISU_DEFAULT_SELECTOR_RDO_THRESH, range is [0,1e+10]
+ .function("setSelectorRDOThresh", optional_override([](basis_encoder& self, float selector_rdo_thresh) {
+ self.m_params.m_selector_rdo_thresh = selector_rdo_thresh;
+ }))
+
+ // Sets endpoint RDO threshold
+ // Default is BASISU_DEFAULT_ENDPOINT_RDO_THRESH, range is [0,1e+10]
+ .function("setEndpointRDOThresh", optional_override([](basis_encoder& self, float endpoint_rdo_thresh) {
+ self.m_params.m_endpoint_rdo_thresh = endpoint_rdo_thresh;
+ }))
+
+ // --- Mip-map options
+
+ // If true mipmaps will be generated from the source images
+ .function("setMipGen", optional_override([](basis_encoder& self, bool mip_gen_flag) {
+ self.m_params.m_mip_gen = mip_gen_flag;
+ }))
+
+ // Set mipmap filter's scale factor
+ // default is 1, range is [.000125, 4.0]
+ .function("setMipScale", optional_override([](basis_encoder& self, float mip_scale) {
+ self.m_params.m_mip_scale = mip_scale;
+ }))
+
+ // Sets the mipmap filter to apply
+ // mip_filter must be < BASISU_MAX_RESAMPLER_FILTERS
+ // See the end of basisu_resample_filters.cpp: g_resample_filters[]
+ .function("setMipFilter", optional_override([](basis_encoder& self, uint32_t mip_filter) {
+ assert(mip_filter < g_num_resample_filters);
+ if (mip_filter < g_num_resample_filters)
+ self.m_params.m_mip_filter = g_resample_filters[mip_filter].name;
+ }))
+
+ // If true mipmap filtering occurs in sRGB space - this generally should match the perceptual parameter.
+ .function("setMipSRGB", optional_override([](basis_encoder& self, bool mip_srgb_flag) {
+ self.m_params.m_mip_srgb = mip_srgb_flag;
+ }))
+
+ // If true, the input is assumed to be a normal map, and the texels of each mipmap will be renormalized before encoding.
+ .function("setMipRenormalize", optional_override([](basis_encoder& self, bool mip_renormalize_flag) {
+ self.m_params.m_mip_renormalize = mip_renormalize_flag;
+ }))
+
+ // If true the source texture will be sampled using wrap addressing during mipmap generation, otherwise clamp.
+ .function("setMipWrapping", optional_override([](basis_encoder& self, bool mip_wrapping_flag) {
+ self.m_params.m_mip_wrapping = mip_wrapping_flag;
+ }))
+
+ // Sets the mipmap generator's smallest allowed dimension.
+ // default is 1, range is [1,16384]
+ .function("setMipSmallestDimension", optional_override([](basis_encoder& self, int mip_smallest_dimension) {
+ self.m_params.m_mip_smallest_dimension = mip_smallest_dimension;
+ }))
+
+ // Sets the .basis texture type.
+ // cBASISTexTypeVideoFrames changes the encoder into video mode.
+ // tex_type is enum basis_texture_type
+ // default is cBASISTexType2D
+ .function("setTexType", optional_override([](basis_encoder& self, uint32_t tex_type) {
+ assert(tex_type < cBASISTexTypeTotal);
+ self.m_params.m_tex_type = (basist::basis_texture_type)tex_type;
+ }))
+
+ .function("setUserData0", optional_override([](basis_encoder& self, uint32_t userdata0) {
+ self.m_params.m_userdata0 = userdata0;
+ }))
+
+ .function("setUserData1", optional_override([](basis_encoder& self, uint32_t userdata1) {
+ self.m_params.m_userdata1 = userdata1;
+ }))
+
+ // UASTC specific flags.
+
+ // Sets the UASTC encoding performance vs. quality tradeoff, and other lesser used UASTC encoder flags.
+ // This is a combination of flags. See cPackUASTCLevelDefault, etc.
+ .function("setPackUASTCFlags", optional_override([](basis_encoder& self, uint32_t pack_uastc_flags) {
+ assert((pack_uastc_flags & cPackUASTCLevelMask) >= cPackUASTCLevelFastest);
+ assert((pack_uastc_flags & cPackUASTCLevelMask) <= cPackUASTCLevelVerySlow);
+ self.m_params.m_pack_uastc_flags = pack_uastc_flags;
+ }))
+
+ // If true, the RDO post-processor will be applied to the encoded UASTC texture data.
+ .function("setRDOUASTC", optional_override([](basis_encoder& self, bool rdo_uastc) {
+ self.m_params.m_rdo_uastc = rdo_uastc;
+ }))
+
+ // Default is 1.0 range is [0.001, 10.0]
+ .function("setRDOUASTCQualityScalar", optional_override([](basis_encoder& self, float rdo_quality) {
+ self.m_params.m_rdo_uastc_quality_scalar = rdo_quality;
+ }))
+
+ // Default is BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, range is [BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX]
+ .function("setRDOUASTCDictSize", optional_override([](basis_encoder& self, int dict_size) {
+ assert((dict_size >= BASISU_RDO_UASTC_DICT_SIZE_MIN) && (dict_size <= BASISU_RDO_UASTC_DICT_SIZE_MAX));
+ self.m_params.m_rdo_uastc_dict_size = dict_size;
+ }))
+
+ // Default is UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, range is [01, 100.0]
+ .function("setRDOUASTCMaxAllowedRMSIncreaseRatio", optional_override([](basis_encoder& self, float rdo_uastc_max_allowed_rms_increase_ratio) {
+ self.m_params.m_rdo_uastc_max_allowed_rms_increase_ratio = rdo_uastc_max_allowed_rms_increase_ratio;
+ }))
+
+ // Default is UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, range is [.01f, 100.0f]
+ .function("setRDOUASTCSkipBlockRMSThresh", optional_override([](basis_encoder& self, float rdo_uastc_skip_block_rms_thresh) {
+ self.m_params.m_rdo_uastc_skip_block_rms_thresh = rdo_uastc_skip_block_rms_thresh;
+ }))
+
+ // --- Low level options
+
+ // Disables selector RDO
+ .function("setNoSelectorRDO", optional_override([](basis_encoder& self, bool no_selector_rdo_flag) {
+ self.m_params.m_no_selector_rdo = no_selector_rdo_flag;
+ }))
+
+ // Disables endpoint RDO
+ .function("setNoEndpointRDO", optional_override([](basis_encoder& self, bool no_endpoint_rdo_flag) {
+ self.m_params.m_no_endpoint_rdo = no_endpoint_rdo_flag;
+ }))
+
+ // Display output PSNR statistics
+ .function("setComputeStats", optional_override([](basis_encoder& self, bool compute_stats_flag) {
+ self.m_params.m_compute_stats = compute_stats_flag;
+ }))
+
+ // Write output .PNG files for debugging
+ .function("setDebugImages", optional_override([](basis_encoder& self, bool debug_images_flag) {
+ self.m_params.m_debug_images = debug_images_flag;
+ }))
+
+ ;
+#endif // BASISU_SUPPORT_ENCODING
+
}
diff --git a/webgl/transcoder/build/basis_transcoder.js b/webgl/transcoder/build/basis_transcoder.js
index 5856bb0..95de34e 100644
--- a/webgl/transcoder/build/basis_transcoder.js
+++ b/webgl/transcoder/build/basis_transcoder.js
@@ -6,16 +6,16 @@ var BASIS = (function() {
function(BASIS) {
BASIS = BASIS || {};
-var Module=typeof BASIS!=="undefined"?BASIS:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":59,"maximum":59+0,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(u8Array[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr){var endPtr=ptr;var idx=endPtr>>1;while(HEAP16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr){var i=0;var str="";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var DYNAMIC_BASE=5561216,DYNAMICTOP_PTR=318176;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var wasmBinaryFile="basis_transcoder.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}__ATINIT__.push({func:function(){___wasm_call_ctors()}});function ___cxa_allocate_exception(size){return _malloc(size)}var ___exception_infos={};var ___exception_last=0;function __ZSt18uncaught_exceptionv(){return __ZSt18uncaught_exceptionv.uncaught_exceptions>0}function ___cxa_throw(ptr,type,destructor){___exception_infos[ptr]={ptr:ptr,adjusted:[ptr],type:type,destructor:destructor,refcount:0,caught:false,rethrown:false};___exception_last=ptr;if(!("uncaught_exception"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exceptions=1}else{__ZSt18uncaught_exceptionv.uncaught_exceptions++}throw ptr}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i>2)+i])}return array}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var endChar=HEAPU8[value+4+length];var endCharSwap=0;if(endChar!=0){endCharSwap=endChar;HEAPU8[value+4+length]=0}var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0){var stringSegment=UTF8ToString(decodeStartPtr);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}if(endCharSwap!=0){HEAPU8[value+4+length]=endCharSwap}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var endChar=HEAP[value+4+length*charSize>>shift];var endCharSwap=0;if(endChar!=0){endCharSwap=endChar;HEAP[value+4+length*charSize>>shift]=0}var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(HEAP[currentBytePtr>>shift]==0){var stringSegment=decodeString(decodeStartPtr);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}if(endCharSwap!=0){HEAP[value+4+length*charSize>>shift]=endCharSwap}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function requireHandle(handle){if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handle_array[handle].value}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __emval_as(handle,returnType,destructorsRef){handle=requireHandle(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=__emval_register(destructors);HEAP32[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}else{return symbol}}var emval_methodCallers=[];function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=requireHandle(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function emval_get_global(){if(typeof globalThis==="object"){return globalThis}return function(){return Function}()("return this")()}function __emval_get_global(name){if(name===0){return __emval_register(emval_get_global())}else{name=getStringOrSymbol(name);return __emval_register(emval_get_global()[name])}}function __emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount);for(var i=0;i>2)+i],"parameter "+i)}return a}function __emval_get_method_caller(argCount,argTypes){var types=__emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function craftEmvalAllocator(argCount){var argsList="";for(var i=0;i> 2) + "+i+'], "parameter '+i+'");\n'+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return __emval_register(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","__emval_register",functionBody)(requireRegisteredType,Module,__emval_register)}var emval_newers={};function __emval_new(handle,argCount,argTypes,args){handle=requireHandle(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)}function __emval_new_cstring(v){return __emval_register(getStringOrSymbol(v))}function __emval_run_destructors(handle){var destructors=emval_handle_array[handle].value;runDestructors(destructors);__emval_decref(handle)}function _abort(){abort()}function _emscripten_get_heap_size(){return HEAPU8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648-PAGE_MULTIPLE;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _setTempRet0($i){setTempRet0($i|0)}embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var asmLibraryArg={"G":___cxa_allocate_exception,"D":___cxa_throw,"A":__embind_register_bool,"t":__embind_register_class,"s":__embind_register_class_constructor,"c":__embind_register_class_function,"z":__embind_register_emval,"j":__embind_register_float,"x":__embind_register_function,"d":__embind_register_integer,"b":__embind_register_memory_view,"k":__embind_register_std_string,"i":__embind_register_std_wstring,"B":__embind_register_void,"r":__emval_as,"m":__emval_call_void_method,"a":__emval_decref,"F":__emval_get_global,"n":__emval_get_method_caller,"p":__emval_get_module_property,"f":__emval_get_property,"h":__emval_incref,"o":__emval_new,"g":__emval_new_cstring,"q":__emval_run_destructors,"E":_abort,"w":_emscripten_memcpy_big,"y":_emscripten_resize_heap,"C":_fd_close,"u":_fd_seek,"l":_fd_write,"memory":wasmMemory,"e":_roundf,"v":_setTempRet0,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["H"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["I"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["J"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["K"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["L"]).apply(null,arguments)};var dynCall_viii=Module["dynCall_viii"]=function(){return(dynCall_viii=Module["dynCall_viii"]=Module["asm"]["M"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return(dynCall_ii=Module["dynCall_ii"]=Module["asm"]["N"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return(dynCall_vi=Module["dynCall_vi"]=Module["asm"]["O"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return(dynCall_v=Module["dynCall_v"]=Module["asm"]["P"]).apply(null,arguments)};var dynCall_iii=Module["dynCall_iii"]=function(){return(dynCall_iii=Module["dynCall_iii"]=Module["asm"]["Q"]).apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){return(dynCall_vii=Module["dynCall_vii"]=Module["asm"]["R"]).apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){return(dynCall_iiii=Module["dynCall_iiii"]=Module["asm"]["S"]).apply(null,arguments)};var dynCall_iiiii=Module["dynCall_iiiii"]=function(){return(dynCall_iiiii=Module["dynCall_iiiii"]=Module["asm"]["T"]).apply(null,arguments)};var dynCall_iiiiii=Module["dynCall_iiiiii"]=function(){return(dynCall_iiiiii=Module["dynCall_iiiiii"]=Module["asm"]["U"]).apply(null,arguments)};var dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=function(){return(dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=Module["asm"]["V"]).apply(null,arguments)};var dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=function(){return(dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=Module["asm"]["W"]).apply(null,arguments)};var dynCall_iidiiii=Module["dynCall_iidiiii"]=function(){return(dynCall_iidiiii=Module["dynCall_iidiiii"]=Module["asm"]["X"]).apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){return(dynCall_jiji=Module["dynCall_jiji"]=Module["asm"]["Y"]).apply(null,arguments)};var dynCall_viiiiii=Module["dynCall_viiiiii"]=function(){return(dynCall_viiiiii=Module["dynCall_viiiiii"]=Module["asm"]["Z"]).apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){return(dynCall_viiiii=Module["dynCall_viiiii"]=Module["asm"]["_"]).apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){return(dynCall_viiii=Module["dynCall_viiii"]=Module["asm"]["$"]).apply(null,arguments)};Module["asm"]=asm;var calledRun;Module["then"]=function(func){if(calledRun){func(Module)}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module)}}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run();
+var Module=typeof BASIS!=="undefined"?BASIS:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="basis_transcoder.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return Promise.resolve().then(getBinary)}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["H"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["I"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}var structRegistrations={};function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function dynCallLegacy(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}return Module["dynCall_"+sig].call(null,ptr)}function dynCall(sig,ptr,args){if(sig.indexOf("j")!=-1){return dynCallLegacy(sig,ptr,args)}return wasmTable.get(ptr).apply(null,args)}function getDynCaller(sig,ptr){assert(sig.indexOf("j")>=0,"getDynCaller should only be called with i64 sigs");var argCache=[];return function(){argCache.length=arguments.length;for(var i=0;i>2)+i])}return array}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_value_object(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor){structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}}function __embind_register_value_object_field(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function requireHandle(handle){if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handle_array[handle].value}function __emval_as(handle,returnType,destructorsRef){handle=requireHandle(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=__emval_register(destructors);HEAP32[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}else{return symbol}}var emval_methodCallers=[];function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=requireHandle(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function emval_get_global(){if(typeof globalThis==="object"){return globalThis}return function(){return Function}()("return this")()}function __emval_get_global(name){if(name===0){return __emval_register(emval_get_global())}else{name=getStringOrSymbol(name);return __emval_register(emval_get_global()[name])}}function __emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount);for(var i=0;i>2)+i],"parameter "+i)}return a}function __emval_get_method_caller(argCount,argTypes){var types=__emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function craftEmvalAllocator(argCount){var argsList="";for(var i=0;i>> 2) + "+i+'], "parameter '+i+'");\n'+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return __emval_register(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","__emval_register",functionBody)(requireRegisteredType,Module,__emval_register)}var emval_newers={};function __emval_new(handle,argCount,argTypes,args){handle=requireHandle(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)}function __emval_new_cstring(v){return __emval_register(getStringOrSymbol(v))}function __emval_run_destructors(handle){var destructors=emval_handle_array[handle].value;runDestructors(destructors);__emval_decref(handle)}function _abort(){abort()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}InternalError=Module["InternalError"]=extendError(Error,"InternalError");embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();__ATINIT__.push({func:function(){___wasm_call_ctors()}});var asmLibraryArg={"G":___cxa_allocate_exception,"F":___cxa_throw,"s":__embind_finalize_value_object,"D":__embind_register_bool,"x":__embind_register_class,"w":__embind_register_class_constructor,"d":__embind_register_class_function,"C":__embind_register_emval,"o":__embind_register_enum,"b":__embind_register_enum_value,"u":__embind_register_float,"j":__embind_register_function,"h":__embind_register_integer,"g":__embind_register_memory_view,"v":__embind_register_std_string,"r":__embind_register_std_wstring,"t":__embind_register_value_object,"c":__embind_register_value_object_field,"E":__embind_register_void,"l":__emval_as,"p":__emval_call_void_method,"a":__emval_decref,"y":__emval_get_global,"q":__emval_get_method_caller,"n":__emval_get_module_property,"e":__emval_get_property,"i":__emval_incref,"m":__emval_new,"f":__emval_new_cstring,"k":__emval_run_destructors,"B":_abort,"z":_emscripten_memcpy_big,"A":_emscripten_resize_heap};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["J"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["K"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["L"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["M"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["N"]).apply(null,arguments)};var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run();
- return BASIS
+ return BASIS.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
- module.exports = BASIS;
- else if (typeof define === 'function' && define['amd'])
- define([], function() { return BASIS; });
- else if (typeof exports === 'object')
- exports["BASIS"] = BASIS;
+ module.exports = BASIS;
+else if (typeof define === 'function' && define['amd'])
+ define([], function() { return BASIS; });
+else if (typeof exports === 'object')
+ exports["BASIS"] = BASIS;
diff --git a/webgl/transcoder/build/basis_transcoder.wasm b/webgl/transcoder/build/basis_transcoder.wasm
index 08e026b3484b78f6ee992385385eba5c7eda532e..bfb0162a50fc96412e39e345af03e9e8e2f0450d 100644
GIT binary patch
delta 114467
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