Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to integrate basis into other applications #93

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ set(BASISU_SRC_LIST ${COMMON_SRC_LIST}
basisu_resampler.cpp
basisu_resample_filters.cpp
basisu_ssim.cpp
basisu_tool.cpp
basisu_astc_decomp.cpp
lodepng.cpp
transcoder/basisu_transcoder.cpp
Expand All @@ -73,8 +72,11 @@ endif()

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${BIN_DIRECTORY})

add_executable(basisu ${BASISU_SRC_LIST})
target_link_libraries(basisu m pthread)
add_library(basisuniversal ${BASISU_SRC_LIST})
target_link_libraries(basisuniversal m pthread)

add_executable(basisu basisu_tool.cpp)
target_link_libraries(basisu basisuniversal)

install(TARGETS basisu DESTINATION bin)

Expand Down
5 changes: 0 additions & 5 deletions basisu_comp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,15 +494,10 @@ namespace basisu
}
}

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_any_source_image_has_alpha)
{
// Alpha slices must be at odd slice indices
Expand Down
3 changes: 2 additions & 1 deletion basisu_comp.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,12 @@ namespace basisu
m_max_selector_clusters(512),
m_quality_level(-1),
m_mip_scale(1.0f, .000125f, 4.0f),
m_mip_filter("kaiser"),
m_mip_smallest_dimension(1, 1, 16384),
m_compression_level((int)BASISU_DEFAULT_COMPRESSION_LEVEL, 0, (int)BASISU_MAX_COMPRESSION_LEVEL),
m_tex_type(basist::cBASISTexType2D),
m_pJob_pool(nullptr)
{
clear();
}

void clear()
Expand Down
111 changes: 77 additions & 34 deletions webgl/transcoder/basis_wrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,17 @@ struct basis_file
}
}

void getImageTranscodedSizesInBytes(const emscripten::val& dst, uint32_t image_index, uint32_t format) {
std::vector<uint32_t> sizes(getNumLevels(image_index));
for (size_t i = 0; i < sizes.size(); ++i) {
sizes[i] = getImageTranscodedSizeInBytes(image_index, i, format);
}

emscripten::val memory = emscripten::val::module_property("HEAPU32")["buffer"];
emscripten::val memoryView = emscripten::val::global("Uint32Array").new_(memory, reinterpret_cast<uintptr_t>(sizes.data()), sizes.size());
dst.call<void>("set", memoryView);
}

uint32_t startTranscoding() {
assert(m_magic == MAGIC);
if (m_magic != MAGIC)
Expand All @@ -164,13 +175,46 @@ struct basis_file
if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
return 0;

std::vector<uint8_t> dst_data;
const uint32_t status = transcodeImage(dst_data, image_index, level_index, format, get_alpha_for_opaque_formats);

emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast<uintptr_t>(dst_data.data()), dst_data.size());

dst.call<void>("set", memoryView);
return status;
}

uint32_t transcodeImageLevels(const emscripten::val& dst, uint32_t image_index, uint32_t format, uint32_t get_alpha_for_opaque_formats) {
assert(m_magic == MAGIC);
if (m_magic != MAGIC)
return 0;

if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
return 0;

const uint32_t numLevels = getNumLevels(image_index);
std::vector<uint8_t> dst_data;

for(uint32_t level = 0; level < numLevels; ++level) {
if (!transcodeImage(dst_data, image_index, level, format, get_alpha_for_opaque_formats))
return 0;
}

emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast<uintptr_t>(dst_data.data()), dst_data.size());

dst.call<void>("set", memoryView);
return 1;
}

bool transcodeImage(std::vector<uint8_t>& dst_data, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t get_alpha_for_opaque_formats) {
const transcoder_texture_format transcoder_format = static_cast<transcoder_texture_format>(format);

uint32_t orig_width, orig_height, total_blocks;
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<uint8_t> dst_data;

uint32_t flags = get_alpha_for_opaque_formats ? basisu_transcoder::cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;

Expand All @@ -182,49 +226,42 @@ struct basis_file
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);
const size_t offset = dst_data.size();
dst_data.resize(offset + bytes_per_slice);

status = m_transcoder.transcode_image_level(
return m_transcoder.transcode_image_level(
m_file.data(), m_file.size(), image_index, level_index,
dst_data.data(), orig_width * orig_height,
dst_data.data() + offset, orig_width * orig_height,
transcoder_format,
flags,
orig_width,
nullptr,
orig_height);
}
else
{
uint32_t bytes_per_block = basis_get_bytes_per_block(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<basist::transcoder_texture_format>(format),
flags);
}
const uint32_t bytes_per_block = basis_get_bytes_per_block(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);
}

emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast<uintptr_t>(dst_data.data()), dst_data.size());
const size_t offset = dst_data.size();
dst_data.resize(offset + required_size);

dst.call<void>("set", memoryView);
return status;
}
return m_transcoder.transcode_image_level(
m_file.data(), m_file.size(), image_index, level_index,
dst_data.data() + offset, required_size / bytes_per_block,
static_cast<basist::transcoder_texture_format>(format),
flags);
}
};

EMSCRIPTEN_BINDINGS(basis_transcoder) {
Expand Down Expand Up @@ -254,12 +291,18 @@ EMSCRIPTEN_BINDINGS(basis_transcoder) {
.function("getImageTranscodedSizeInBytes", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex, uint32_t format) {
return self.getImageTranscodedSizeInBytes(imageIndex, levelIndex, format);
}))
.function("getImageTranscodedSizesInBytes", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t format) {
return self.getImageTranscodedSizesInBytes(dst, imageIndex, format);
}))
.function("startTranscoding", optional_override([](basis_file& self) {
return self.startTranscoding();
}))
.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);
}))
.function("transcodeImageLevels", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t format, uint32_t getAlphaForOpaqueFormats) {
return self.transcodeImageLevels(dst, imageIndex, format, getAlphaForOpaqueFormats);
}))
;

}
2 changes: 1 addition & 1 deletion webgl/transcoder/build/basis_transcoder.js

Large diffs are not rendered by default.

Binary file modified webgl/transcoder/build/basis_transcoder.wasm
Binary file not shown.