Add ktx
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
build/
|
||||
|
||||
# VS project and working files
|
||||
*.vcxproj.user
|
||||
.vs/
|
||||
Debug/
|
||||
Release/
|
||||
|
||||
|
||||
# Mac finder
|
||||
.DS_Store
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://github.com/BinomialLLC/basis_universal.git
|
||||
branch = master
|
||||
commit = 1f4b564ae0b8ec1e67f21f058e53112d0405a25a
|
||||
parent = cb45eadca7fed568d9f6f51477ca897d1ec2732a
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: basis_universal
|
||||
Source: https://github.com/BinomialLLC/basis_universal
|
||||
|
||||
# We have asked Binomial about REUSE compliance for their repo, see https://github.com/BinomialLLC/basis_universal/issues/165
|
||||
Files: *
|
||||
Copyright: 2019-2021 Binomial LLC
|
||||
License: Apache-2.0
|
||||
|
||||
Files: zstd/*
|
||||
Copyright: 2016-present, Facebook, Inc.
|
||||
License: BSD
|
||||
|
||||
Files: OpenCL/*
|
||||
Copyright: Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
License: Apache-2.0
|
||||
|
||||
Vendored
+211
@@ -0,0 +1,211 @@
|
||||
project(basisu)
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
option(STATIC "static linking" FALSE)
|
||||
option(SAN "sanitize" FALSE)
|
||||
|
||||
# For MSVC builds default to SSE enabled, and determine if it's a 64-bit (-A x64) vs. 32-bit (-A Win32) build.
|
||||
if (MSVC)
|
||||
option(SSE "SSE 4.1 support" TRUE)
|
||||
if ( CMAKE_GENERATOR_PLATFORM STREQUAL Win32 )
|
||||
set(BUILD_X64 0)
|
||||
else()
|
||||
set(BUILD_X64 1)
|
||||
endif()
|
||||
else()
|
||||
option(SSE "SSE 4.1 support" FALSE)
|
||||
option(BUILD_X64 "build 64-bit" TRUE)
|
||||
endif()
|
||||
|
||||
option(ZSTD "ZSTD support for KTX2 transcoding/encoding" TRUE)
|
||||
option(OPENCL "OpenCL support in encoder" FALSE)
|
||||
|
||||
message("Initial BUILD_X64=${BUILD_X64}")
|
||||
message("Initial CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
|
||||
message("Initial SSE=${SSE}")
|
||||
message("Initial ZSTD=${ZSTD}")
|
||||
message("Initial OPENCL=${OPENCL}")
|
||||
message("Initial SAN=${SAN}")
|
||||
|
||||
if (NOT MSVC)
|
||||
# With MSVC builds we use the Khronos lib/include files in the project's "OpenCL" directory, to completely avoid requiring fiddly to install vendor SDK's.
|
||||
# Otherwise we use the system's (if any).
|
||||
find_package( OpenCL )
|
||||
message(STATUS "OpenCL found: ${OPENCL_FOUND}")
|
||||
message(STATUS "OpenCL includes: ${OpenCL_INCLUDE_DIRS}")
|
||||
message(STATUS "OpenCL libraries: ${OpenCL_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
if( NOT CMAKE_BUILD_TYPE )
|
||||
set( CMAKE_BUILD_TYPE Release )
|
||||
endif()
|
||||
|
||||
message( ${PROJECT_NAME} " build type: " ${CMAKE_BUILD_TYPE} )
|
||||
|
||||
if (BUILD_X64)
|
||||
message("Building 64-bit")
|
||||
else()
|
||||
message("Building 32-bit")
|
||||
endif()
|
||||
|
||||
if (SSE)
|
||||
message("SSE enabled")
|
||||
else()
|
||||
message("SSE disabled")
|
||||
endif()
|
||||
|
||||
if (ZSTD)
|
||||
message("Zstandard enabled")
|
||||
else()
|
||||
message("Zstandard disabled")
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
|
||||
if (SAN)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS -std=c++11)
|
||||
set(GCC_COMPILE_FLAGS "-fvisibility=hidden -fPIC -fno-strict-aliasing -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -Wextra -Wno-unused-local-typedefs -Wno-unused-value -Wno-unused-parameter -Wno-unused-variable")
|
||||
|
||||
if (NOT BUILD_X64)
|
||||
set(GCC_COMPILE_FLAGS "${GCC_COMPILE_FLAGS} -m32")
|
||||
endif()
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -DBASISU_SUPPORT_SSE=0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -DBASISU_SUPPORT_SSE=0")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS}")
|
||||
elseif (STATIC)
|
||||
if (SSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS} -static-libgcc -static-libstdc++ -static")
|
||||
else()
|
||||
if (SSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS} -Wl,-rpath .")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COMPILE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${GCC_COMPILE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${GCC_COMPILE_FLAGS} -D_DEBUG")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${GCC_COMPILE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${GCC_COMPILE_FLAGS} -D_DEBUG")
|
||||
else()
|
||||
if (SSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(BASISU_SRC_LIST ${COMMON_SRC_LIST}
|
||||
basisu_tool.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_gpu_texture.cpp
|
||||
encoder/basisu_pvrtc1_4.cpp
|
||||
encoder/basisu_resampler.cpp
|
||||
encoder/basisu_resample_filters.cpp
|
||||
encoder/basisu_ssim.cpp
|
||||
encoder/basisu_uastc_enc.cpp
|
||||
encoder/basisu_bc7enc.cpp
|
||||
encoder/jpgd.cpp
|
||||
encoder/basisu_kernels_sse.cpp
|
||||
encoder/basisu_opencl.cpp
|
||||
encoder/pvpngreader.cpp
|
||||
transcoder/basisu_transcoder.cpp
|
||||
)
|
||||
|
||||
if (ZSTD)
|
||||
set(BASISU_SRC_LIST ${BASISU_SRC_LIST} zstd/zstd.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(BIN_DIRECTORY "bin_osx")
|
||||
else()
|
||||
set(BIN_DIRECTORY "bin")
|
||||
endif()
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${BIN_DIRECTORY})
|
||||
|
||||
add_executable(basisu ${BASISU_SRC_LIST})
|
||||
|
||||
if (ZSTD)
|
||||
target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1)
|
||||
else()
|
||||
target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
# For Non-Windows builds, let cmake try and find the system OpenCL headers/libs for us.
|
||||
if (OPENCL_FOUND)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_OPENCL=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_OPENCL=1")
|
||||
|
||||
target_include_directories( basisu PRIVATE ${OpenCL_INCLUDE_DIRS} )
|
||||
set(BASISU_EXTRA_LIBS ${OpenCL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
else()
|
||||
# For Windows builds, we use our local copies of the OpenCL import lib and Khronos headers.
|
||||
if (OPENCL)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_OPENCL=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_OPENCL=1")
|
||||
|
||||
target_include_directories( basisu PRIVATE "OpenCL" )
|
||||
|
||||
if ( BUILD_X64 )
|
||||
target_link_libraries( basisu PRIVATE "OpenCL/lib/OpenCL64" )
|
||||
else()
|
||||
target_link_libraries( basisu PRIVATE "OpenCL/lib/OpenCL" )
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
target_link_libraries(basisu m pthread ${BASISU_EXTRA_LIBS})
|
||||
endif()
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
install(TARGETS basisu DESTINATION bin)
|
||||
|
||||
if (UNIX)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
if (APPLE)
|
||||
add_custom_command(TARGET basisu POST_BUILD COMMAND strip -X -x ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/basisu)
|
||||
else()
|
||||
add_custom_command(TARGET basisu POST_BUILD COMMAND strip -g -X -x ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/basisu)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64"
|
||||
],
|
||||
"name": "x64-Release",
|
||||
"includePath": [
|
||||
"${env.INCLUDE}",
|
||||
"${workspaceRoot}\\**"
|
||||
],
|
||||
"defines": [
|
||||
"WIN32",
|
||||
"NDEBUG",
|
||||
"UNICODE",
|
||||
"_UNICODE"
|
||||
],
|
||||
"intelliSenseMode": "windows-msvc-x64"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
|
||||
AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution
|
||||
as defined by Sections 1 through 9 of this document.
|
||||
|
||||
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct
|
||||
or indirect, to cause the direction or management of such entity, whether
|
||||
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
|
||||
of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
|
||||
granted by this License.
|
||||
|
||||
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation
|
||||
or translation of a Source form, including but not limited to compiled object
|
||||
code, generated documentation, and conversions to other media types.
|
||||
|
||||
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form,
|
||||
made available under the License, as indicated by a copyright notice that
|
||||
is included in or attached to the work (an example is provided in the Appendix
|
||||
below).
|
||||
|
||||
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form,
|
||||
that is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative
|
||||
Works shall not include works that remain separable from, or merely link (or
|
||||
bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative
|
||||
Works thereof, that is intentionally submitted to Licensor for inclusion in
|
||||
the Work by the copyright owner or by an individual or Legal Entity authorized
|
||||
to submit on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication
|
||||
sent to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor
|
||||
for the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently incorporated
|
||||
within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
|
||||
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
|
||||
the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License,
|
||||
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section) patent
|
||||
license to make, have made, use, offer to sell, sell, import, and otherwise
|
||||
transfer the Work, where such license applies only to those patent claims
|
||||
licensable by such Contributor that are necessarily infringed by their Contribution(s)
|
||||
alone or by combination of their Contribution(s) with the Work to which such
|
||||
Contribution(s) was submitted. If You institute patent litigation against
|
||||
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that the Work or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses granted to You
|
||||
under this License for that Work shall terminate as of the date such litigation
|
||||
is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||
Derivative Works thereof in any medium, with or without modifications, and
|
||||
in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or Derivative Works a copy
|
||||
of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices stating that
|
||||
You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source
|
||||
form of the Work, excluding those notices that do not pertain to any part
|
||||
of the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable copy
|
||||
of the attribution notices contained within such NOTICE file, excluding those
|
||||
notices that do not pertain to any part of the Derivative Works, in at least
|
||||
one of the following places: within a NOTICE text file distributed as part
|
||||
of the Derivative Works; within the Source form or documentation, if provided
|
||||
along with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works
|
||||
that You distribute, alongside or as an addendum to the NOTICE text from the
|
||||
Work, provided that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction,
|
||||
or distribution of Your modifications, or for any such Derivative Works as
|
||||
a whole, provided Your use, reproduction, and distribution of the Work otherwise
|
||||
complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
||||
Contribution intentionally submitted for inclusion in the Work by You to the
|
||||
Licensor shall be under the terms and conditions of this License, without
|
||||
any additional terms or conditions. Notwithstanding the above, nothing herein
|
||||
shall supersede or modify the terms of any separate license agreement you
|
||||
may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names,
|
||||
trademarks, service marks, or product names of the Licensor, except as required
|
||||
for reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
|
||||
in writing, Licensor provides the Work (and each Contributor provides its
|
||||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied, including, without limitation, any warranties
|
||||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
|
||||
of using or redistributing the Work and assume any risks associated with Your
|
||||
exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether
|
||||
in tort (including negligence), contract, or otherwise, unless required by
|
||||
applicable law (such as deliberate and grossly negligent acts) or agreed to
|
||||
in writing, shall any Contributor be liable to You for damages, including
|
||||
any direct, indirect, special, incidental, or consequential damages of any
|
||||
character arising as a result of this License or out of the use or inability
|
||||
to use the Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all other commercial
|
||||
damages or losses), even if such Contributor has been advised of the possibility
|
||||
of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work
|
||||
or Derivative Works thereof, You may choose to offer, and charge a fee for,
|
||||
acceptance of support, warranty, indemnity, or other liability obligations
|
||||
and/or rights consistent with this License. However, in accepting such obligations,
|
||||
You may act only on Your own behalf and on Your sole responsibility, not on
|
||||
behalf of any other Contributor, and only if You agree to indemnify, defend,
|
||||
and hold each Contributor harmless for any liability incurred by, or claims
|
||||
asserted against, such Contributor by reason of your accepting any such warranty
|
||||
or additional liability. END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
|
||||
information. (Don't include the brackets!) The text should be enclosed in
|
||||
the appropriate comment syntax for the file format. We also recommend that
|
||||
a file or class name and description of purpose be included on the same "printed
|
||||
page" as the copyright notice for easier identification within third-party
|
||||
archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
BSD License
|
||||
|
||||
Copyright (c) <year> <copyright holders> All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Facebook nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
Copyright (c) <year> <copyright holders>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
Vendored
+1929
File diff suppressed because it is too large
Load Diff
+128
@@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_D3D10_H
|
||||
#define __OPENCL_CL_D3D10_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >=1500
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4201 )
|
||||
#endif
|
||||
#endif
|
||||
#include <d3d10.h>
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >=1500
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
#endif
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_platform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* cl_khr_d3d10_sharing */
|
||||
#define cl_khr_d3d10_sharing 1
|
||||
|
||||
typedef cl_uint cl_d3d10_device_source_khr;
|
||||
typedef cl_uint cl_d3d10_device_set_khr;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Error Codes */
|
||||
#define CL_INVALID_D3D10_DEVICE_KHR -1002
|
||||
#define CL_INVALID_D3D10_RESOURCE_KHR -1003
|
||||
#define CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR -1004
|
||||
#define CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR -1005
|
||||
|
||||
/* cl_d3d10_device_source_nv */
|
||||
#define CL_D3D10_DEVICE_KHR 0x4010
|
||||
#define CL_D3D10_DXGI_ADAPTER_KHR 0x4011
|
||||
|
||||
/* cl_d3d10_device_set_nv */
|
||||
#define CL_PREFERRED_DEVICES_FOR_D3D10_KHR 0x4012
|
||||
#define CL_ALL_DEVICES_FOR_D3D10_KHR 0x4013
|
||||
|
||||
/* cl_context_info */
|
||||
#define CL_CONTEXT_D3D10_DEVICE_KHR 0x4014
|
||||
#define CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR 0x402C
|
||||
|
||||
/* cl_mem_info */
|
||||
#define CL_MEM_D3D10_RESOURCE_KHR 0x4015
|
||||
|
||||
/* cl_image_info */
|
||||
#define CL_IMAGE_D3D10_SUBRESOURCE_KHR 0x4016
|
||||
|
||||
/* cl_command_type */
|
||||
#define CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR 0x4017
|
||||
#define CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR 0x4018
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef cl_int (CL_API_CALL *clGetDeviceIDsFromD3D10KHR_fn)(
|
||||
cl_platform_id platform,
|
||||
cl_d3d10_device_source_khr d3d_device_source,
|
||||
void * d3d_object,
|
||||
cl_d3d10_device_set_khr d3d_device_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id * devices,
|
||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D10BufferKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D10Buffer * resource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D10Texture2DKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D10Texture2D * resource,
|
||||
UINT subresource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D10Texture3DKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D10Texture3D * resource,
|
||||
UINT subresource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireD3D10ObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseD3D10ObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_D3D10_H */
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_D3D11_H
|
||||
#define __OPENCL_CL_D3D11_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >=1500
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4201 )
|
||||
#endif
|
||||
#endif
|
||||
#include <d3d11.h>
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >=1500
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
#endif
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_platform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* cl_khr_d3d11_sharing */
|
||||
#define cl_khr_d3d11_sharing 1
|
||||
|
||||
typedef cl_uint cl_d3d11_device_source_khr;
|
||||
typedef cl_uint cl_d3d11_device_set_khr;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Error Codes */
|
||||
#define CL_INVALID_D3D11_DEVICE_KHR -1006
|
||||
#define CL_INVALID_D3D11_RESOURCE_KHR -1007
|
||||
#define CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR -1008
|
||||
#define CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR -1009
|
||||
|
||||
/* cl_d3d11_device_source */
|
||||
#define CL_D3D11_DEVICE_KHR 0x4019
|
||||
#define CL_D3D11_DXGI_ADAPTER_KHR 0x401A
|
||||
|
||||
/* cl_d3d11_device_set */
|
||||
#define CL_PREFERRED_DEVICES_FOR_D3D11_KHR 0x401B
|
||||
#define CL_ALL_DEVICES_FOR_D3D11_KHR 0x401C
|
||||
|
||||
/* cl_context_info */
|
||||
#define CL_CONTEXT_D3D11_DEVICE_KHR 0x401D
|
||||
#define CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR 0x402D
|
||||
|
||||
/* cl_mem_info */
|
||||
#define CL_MEM_D3D11_RESOURCE_KHR 0x401E
|
||||
|
||||
/* cl_image_info */
|
||||
#define CL_IMAGE_D3D11_SUBRESOURCE_KHR 0x401F
|
||||
|
||||
/* cl_command_type */
|
||||
#define CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR 0x4020
|
||||
#define CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR 0x4021
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef cl_int (CL_API_CALL *clGetDeviceIDsFromD3D11KHR_fn)(
|
||||
cl_platform_id platform,
|
||||
cl_d3d11_device_source_khr d3d_device_source,
|
||||
void * d3d_object,
|
||||
cl_d3d11_device_set_khr d3d_device_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id * devices,
|
||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D11BufferKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D11Buffer * resource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D11Texture2DKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D11Texture2D * resource,
|
||||
UINT subresource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromD3D11Texture3DKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
ID3D11Texture3D * resource,
|
||||
UINT subresource,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireD3D11ObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseD3D11ObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_D3D11_H */
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_DX9_MEDIA_SHARING_H
|
||||
#define __OPENCL_CL_DX9_MEDIA_SHARING_H
|
||||
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_platform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* cl_khr_dx9_media_sharing */
|
||||
#define cl_khr_dx9_media_sharing 1
|
||||
|
||||
typedef cl_uint cl_dx9_media_adapter_type_khr;
|
||||
typedef cl_uint cl_dx9_media_adapter_set_khr;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <d3d9.h>
|
||||
typedef struct _cl_dx9_surface_info_khr
|
||||
{
|
||||
IDirect3DSurface9 *resource;
|
||||
HANDLE shared_handle;
|
||||
} cl_dx9_surface_info_khr;
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Error Codes */
|
||||
#define CL_INVALID_DX9_MEDIA_ADAPTER_KHR -1010
|
||||
#define CL_INVALID_DX9_MEDIA_SURFACE_KHR -1011
|
||||
#define CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR -1012
|
||||
#define CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR -1013
|
||||
|
||||
/* cl_media_adapter_type_khr */
|
||||
#define CL_ADAPTER_D3D9_KHR 0x2020
|
||||
#define CL_ADAPTER_D3D9EX_KHR 0x2021
|
||||
#define CL_ADAPTER_DXVA_KHR 0x2022
|
||||
|
||||
/* cl_media_adapter_set_khr */
|
||||
#define CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2023
|
||||
#define CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2024
|
||||
|
||||
/* cl_context_info */
|
||||
#define CL_CONTEXT_ADAPTER_D3D9_KHR 0x2025
|
||||
#define CL_CONTEXT_ADAPTER_D3D9EX_KHR 0x2026
|
||||
#define CL_CONTEXT_ADAPTER_DXVA_KHR 0x2027
|
||||
|
||||
/* cl_mem_info */
|
||||
#define CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR 0x2028
|
||||
#define CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR 0x2029
|
||||
|
||||
/* cl_image_info */
|
||||
#define CL_IMAGE_DX9_MEDIA_PLANE_KHR 0x202A
|
||||
|
||||
/* cl_command_type */
|
||||
#define CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR 0x202B
|
||||
#define CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR 0x202C
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef cl_int (CL_API_CALL *clGetDeviceIDsFromDX9MediaAdapterKHR_fn)(
|
||||
cl_platform_id platform,
|
||||
cl_uint num_media_adapters,
|
||||
cl_dx9_media_adapter_type_khr * media_adapter_type,
|
||||
void * media_adapters,
|
||||
cl_dx9_media_adapter_set_khr media_adapter_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id * devices,
|
||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromDX9MediaSurfaceKHR_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_dx9_media_adapter_type_khr adapter_type,
|
||||
void * surface_info,
|
||||
cl_uint plane,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireDX9MediaSurfacesKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseDX9MediaSurfacesKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
/***************************************
|
||||
* cl_intel_dx9_media_sharing extension *
|
||||
****************************************/
|
||||
|
||||
#define cl_intel_dx9_media_sharing 1
|
||||
|
||||
typedef cl_uint cl_dx9_device_source_intel;
|
||||
typedef cl_uint cl_dx9_device_set_intel;
|
||||
|
||||
/* error codes */
|
||||
#define CL_INVALID_DX9_DEVICE_INTEL -1010
|
||||
#define CL_INVALID_DX9_RESOURCE_INTEL -1011
|
||||
#define CL_DX9_RESOURCE_ALREADY_ACQUIRED_INTEL -1012
|
||||
#define CL_DX9_RESOURCE_NOT_ACQUIRED_INTEL -1013
|
||||
|
||||
/* cl_dx9_device_source_intel */
|
||||
#define CL_D3D9_DEVICE_INTEL 0x4022
|
||||
#define CL_D3D9EX_DEVICE_INTEL 0x4070
|
||||
#define CL_DXVA_DEVICE_INTEL 0x4071
|
||||
|
||||
/* cl_dx9_device_set_intel */
|
||||
#define CL_PREFERRED_DEVICES_FOR_DX9_INTEL 0x4024
|
||||
#define CL_ALL_DEVICES_FOR_DX9_INTEL 0x4025
|
||||
|
||||
/* cl_context_info */
|
||||
#define CL_CONTEXT_D3D9_DEVICE_INTEL 0x4026
|
||||
#define CL_CONTEXT_D3D9EX_DEVICE_INTEL 0x4072
|
||||
#define CL_CONTEXT_DXVA_DEVICE_INTEL 0x4073
|
||||
|
||||
/* cl_mem_info */
|
||||
#define CL_MEM_DX9_RESOURCE_INTEL 0x4027
|
||||
#define CL_MEM_DX9_SHARED_HANDLE_INTEL 0x4074
|
||||
|
||||
/* cl_image_info */
|
||||
#define CL_IMAGE_DX9_PLANE_INTEL 0x4075
|
||||
|
||||
/* cl_command_type */
|
||||
#define CL_COMMAND_ACQUIRE_DX9_OBJECTS_INTEL 0x402A
|
||||
#define CL_COMMAND_RELEASE_DX9_OBJECTS_INTEL 0x402B
|
||||
/******************************************************************************/
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetDeviceIDsFromDX9INTEL(
|
||||
cl_platform_id platform,
|
||||
cl_dx9_device_source_intel dx9_device_source,
|
||||
void* dx9_object,
|
||||
cl_dx9_device_set_intel dx9_device_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id* devices,
|
||||
cl_uint* num_devices) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
typedef cl_int (CL_API_CALL* clGetDeviceIDsFromDX9INTEL_fn)(
|
||||
cl_platform_id platform,
|
||||
cl_dx9_device_source_intel dx9_device_source,
|
||||
void* dx9_object,
|
||||
cl_dx9_device_set_intel dx9_device_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id* devices,
|
||||
cl_uint* num_devices) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromDX9MediaSurfaceINTEL(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
IDirect3DSurface9* resource,
|
||||
HANDLE sharedHandle,
|
||||
UINT plane,
|
||||
cl_int* errcode_ret) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromDX9MediaSurfaceINTEL_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
IDirect3DSurface9* resource,
|
||||
HANDLE sharedHandle,
|
||||
UINT plane,
|
||||
cl_int* errcode_ret) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueAcquireDX9ObjectsINTEL(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireDX9ObjectsINTEL_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueReleaseDX9ObjectsINTEL(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseDX9ObjectsINTEL_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_DX9_MEDIA_SHARING_H */
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include <CL/cl_dx9_media_sharing.h>
|
||||
#pragma message("The Intel DX9 media sharing extensions have been moved into cl_dx9_media_sharing.h. Please include cl_dx9_media_sharing.h directly.")
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_EGL_H
|
||||
#define __OPENCL_CL_EGL_H
|
||||
|
||||
#include <CL/cl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Command type for events created with clEnqueueAcquireEGLObjectsKHR */
|
||||
#define CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR 0x202F
|
||||
#define CL_COMMAND_ACQUIRE_EGL_OBJECTS_KHR 0x202D
|
||||
#define CL_COMMAND_RELEASE_EGL_OBJECTS_KHR 0x202E
|
||||
|
||||
/* Error type for clCreateFromEGLImageKHR */
|
||||
#define CL_INVALID_EGL_OBJECT_KHR -1093
|
||||
#define CL_EGL_RESOURCE_NOT_ACQUIRED_KHR -1092
|
||||
|
||||
/* CLeglImageKHR is an opaque handle to an EGLImage */
|
||||
typedef void* CLeglImageKHR;
|
||||
|
||||
/* CLeglDisplayKHR is an opaque handle to an EGLDisplay */
|
||||
typedef void* CLeglDisplayKHR;
|
||||
|
||||
/* CLeglSyncKHR is an opaque handle to an EGLSync object */
|
||||
typedef void* CLeglSyncKHR;
|
||||
|
||||
/* properties passed to clCreateFromEGLImageKHR */
|
||||
typedef intptr_t cl_egl_image_properties_khr;
|
||||
|
||||
|
||||
#define cl_khr_egl_image 1
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromEGLImageKHR(cl_context context,
|
||||
CLeglDisplayKHR egldisplay,
|
||||
CLeglImageKHR eglimage,
|
||||
cl_mem_flags flags,
|
||||
const cl_egl_image_properties_khr * properties,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_mem (CL_API_CALL *clCreateFromEGLImageKHR_fn)(
|
||||
cl_context context,
|
||||
CLeglDisplayKHR egldisplay,
|
||||
CLeglImageKHR eglimage,
|
||||
cl_mem_flags flags,
|
||||
const cl_egl_image_properties_khr * properties,
|
||||
cl_int * errcode_ret);
|
||||
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueAcquireEGLObjectsKHR(cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireEGLObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event);
|
||||
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueReleaseEGLObjectsKHR(cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseEGLObjectsKHR_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event);
|
||||
|
||||
|
||||
#define cl_khr_egl_event 1
|
||||
|
||||
extern CL_API_ENTRY cl_event CL_API_CALL
|
||||
clCreateEventFromEGLSyncKHR(cl_context context,
|
||||
CLeglSyncKHR sync,
|
||||
CLeglDisplayKHR display,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_event (CL_API_CALL *clCreateEventFromEGLSyncKHR_fn)(
|
||||
cl_context context,
|
||||
CLeglSyncKHR sync,
|
||||
CLeglDisplayKHR display,
|
||||
cl_int * errcode_ret);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_EGL_H */
|
||||
+1723
File diff suppressed because it is too large
Load Diff
+19
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <CL/cl_ext.h>
|
||||
#pragma message("The Intel extensions have been moved into cl_ext.h. Please include cl_ext.h directly.")
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2021 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_GL_H
|
||||
#define __OPENCL_CL_GL_H
|
||||
|
||||
#include <CL/cl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef cl_uint cl_gl_object_type;
|
||||
typedef cl_uint cl_gl_texture_info;
|
||||
typedef cl_uint cl_gl_platform_info;
|
||||
typedef struct __GLsync *cl_GLsync;
|
||||
|
||||
/* cl_gl_object_type = 0x2000 - 0x200F enum values are currently taken */
|
||||
#define CL_GL_OBJECT_BUFFER 0x2000
|
||||
#define CL_GL_OBJECT_TEXTURE2D 0x2001
|
||||
#define CL_GL_OBJECT_TEXTURE3D 0x2002
|
||||
#define CL_GL_OBJECT_RENDERBUFFER 0x2003
|
||||
#ifdef CL_VERSION_1_2
|
||||
#define CL_GL_OBJECT_TEXTURE2D_ARRAY 0x200E
|
||||
#define CL_GL_OBJECT_TEXTURE1D 0x200F
|
||||
#define CL_GL_OBJECT_TEXTURE1D_ARRAY 0x2010
|
||||
#define CL_GL_OBJECT_TEXTURE_BUFFER 0x2011
|
||||
#endif
|
||||
|
||||
/* cl_gl_texture_info */
|
||||
#define CL_GL_TEXTURE_TARGET 0x2004
|
||||
#define CL_GL_MIPMAP_LEVEL 0x2005
|
||||
#ifdef CL_VERSION_1_2
|
||||
#define CL_GL_NUM_SAMPLES 0x2012
|
||||
#endif
|
||||
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromGLBuffer(cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_GLuint bufobj,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromGLTexture(cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_GLenum target,
|
||||
cl_GLint miplevel,
|
||||
cl_GLuint texture,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
#endif
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromGLRenderbuffer(cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_GLuint renderbuffer,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetGLObjectInfo(cl_mem memobj,
|
||||
cl_gl_object_type * gl_object_type,
|
||||
cl_GLuint * gl_object_name) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetGLTextureInfo(cl_mem memobj,
|
||||
cl_gl_texture_info param_name,
|
||||
size_t param_value_size,
|
||||
void * param_value,
|
||||
size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueAcquireGLObjects(cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueReleaseGLObjects(cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem * mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event * event_wait_list,
|
||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
|
||||
/* Deprecated OpenCL 1.1 APIs */
|
||||
extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
|
||||
clCreateFromGLTexture2D(cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_GLenum target,
|
||||
cl_GLint miplevel,
|
||||
cl_GLuint texture,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
|
||||
|
||||
extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
|
||||
clCreateFromGLTexture3D(cl_context context,
|
||||
cl_mem_flags flags,
|
||||
cl_GLenum target,
|
||||
cl_GLint miplevel,
|
||||
cl_GLuint texture,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
|
||||
|
||||
/* cl_khr_gl_sharing extension */
|
||||
|
||||
#define cl_khr_gl_sharing 1
|
||||
|
||||
typedef cl_uint cl_gl_context_info;
|
||||
|
||||
/* Additional Error Codes */
|
||||
#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
|
||||
|
||||
/* cl_gl_context_info */
|
||||
#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
|
||||
#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
|
||||
|
||||
/* Additional cl_context_properties */
|
||||
#define CL_GL_CONTEXT_KHR 0x2008
|
||||
#define CL_EGL_DISPLAY_KHR 0x2009
|
||||
#define CL_GLX_DISPLAY_KHR 0x200A
|
||||
#define CL_WGL_HDC_KHR 0x200B
|
||||
#define CL_CGL_SHAREGROUP_KHR 0x200C
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetGLContextInfoKHR(const cl_context_properties * properties,
|
||||
cl_gl_context_info param_name,
|
||||
size_t param_value_size,
|
||||
void * param_value,
|
||||
size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
|
||||
const cl_context_properties * properties,
|
||||
cl_gl_context_info param_name,
|
||||
size_t param_value_size,
|
||||
void * param_value,
|
||||
size_t * param_value_size_ret);
|
||||
|
||||
/*
|
||||
* cl_khr_gl_event extension
|
||||
*/
|
||||
#define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D
|
||||
|
||||
extern CL_API_ENTRY cl_event CL_API_CALL
|
||||
clCreateEventFromGLsyncKHR(cl_context context,
|
||||
cl_GLsync sync,
|
||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_GL_H */
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2021 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include <CL/cl_gl.h>
|
||||
#pragma message("All OpenGL-related extensions have been moved into cl_gl.h. Please include cl_gl.h directly.")
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* This is a header-only utility library that provides OpenCL host code with
|
||||
* routines for converting to/from cl_half values.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* #include <CL/cl_half.h>
|
||||
* ...
|
||||
* cl_half h = cl_half_from_float(0.5f, CL_HALF_RTE);
|
||||
* cl_float f = cl_half_to_float(h);
|
||||
*/
|
||||
|
||||
#ifndef OPENCL_CL_HALF_H
|
||||
#define OPENCL_CL_HALF_H
|
||||
|
||||
#include <CL/cl_platform.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Rounding mode used when converting to cl_half.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CL_HALF_RTE, // round to nearest even
|
||||
CL_HALF_RTZ, // round towards zero
|
||||
CL_HALF_RTP, // round towards positive infinity
|
||||
CL_HALF_RTN, // round towards negative infinity
|
||||
} cl_half_rounding_mode;
|
||||
|
||||
|
||||
/* Private utility macros. */
|
||||
#define CL_HALF_EXP_MASK 0x7C00
|
||||
#define CL_HALF_MAX_FINITE_MAG 0x7BFF
|
||||
|
||||
|
||||
/*
|
||||
* Utility to deal with values that overflow when converting to half precision.
|
||||
*/
|
||||
static inline cl_half cl_half_handle_overflow(cl_half_rounding_mode rounding_mode,
|
||||
uint16_t sign)
|
||||
{
|
||||
if (rounding_mode == CL_HALF_RTZ)
|
||||
{
|
||||
// Round overflow towards zero -> largest finite number (preserving sign)
|
||||
return (sign << 15) | CL_HALF_MAX_FINITE_MAG;
|
||||
}
|
||||
else if (rounding_mode == CL_HALF_RTP && sign)
|
||||
{
|
||||
// Round negative overflow towards positive infinity -> most negative finite number
|
||||
return (1 << 15) | CL_HALF_MAX_FINITE_MAG;
|
||||
}
|
||||
else if (rounding_mode == CL_HALF_RTN && !sign)
|
||||
{
|
||||
// Round positive overflow towards negative infinity -> largest finite number
|
||||
return CL_HALF_MAX_FINITE_MAG;
|
||||
}
|
||||
|
||||
// Overflow to infinity
|
||||
return (sign << 15) | CL_HALF_EXP_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility to deal with values that underflow when converting to half precision.
|
||||
*/
|
||||
static inline cl_half cl_half_handle_underflow(cl_half_rounding_mode rounding_mode,
|
||||
uint16_t sign)
|
||||
{
|
||||
if (rounding_mode == CL_HALF_RTP && !sign)
|
||||
{
|
||||
// Round underflow towards positive infinity -> smallest positive value
|
||||
return (sign << 15) | 1;
|
||||
}
|
||||
else if (rounding_mode == CL_HALF_RTN && sign)
|
||||
{
|
||||
// Round underflow towards negative infinity -> largest negative value
|
||||
return (sign << 15) | 1;
|
||||
}
|
||||
|
||||
// Flush to zero
|
||||
return (sign << 15);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a cl_float to a cl_half.
|
||||
*/
|
||||
static inline cl_half cl_half_from_float(cl_float f, cl_half_rounding_mode rounding_mode)
|
||||
{
|
||||
// Type-punning to get direct access to underlying bits
|
||||
union
|
||||
{
|
||||
cl_float f;
|
||||
uint32_t i;
|
||||
} f32;
|
||||
f32.f = f;
|
||||
|
||||
// Extract sign bit
|
||||
uint16_t sign = f32.i >> 31;
|
||||
|
||||
// Extract FP32 exponent and mantissa
|
||||
uint32_t f_exp = (f32.i >> (CL_FLT_MANT_DIG - 1)) & 0xFF;
|
||||
uint32_t f_mant = f32.i & ((1 << (CL_FLT_MANT_DIG - 1)) - 1);
|
||||
|
||||
// Remove FP32 exponent bias
|
||||
int32_t exp = f_exp - CL_FLT_MAX_EXP + 1;
|
||||
|
||||
// Add FP16 exponent bias
|
||||
uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
|
||||
|
||||
// Position of the bit that will become the FP16 mantissa LSB
|
||||
uint32_t lsb_pos = CL_FLT_MANT_DIG - CL_HALF_MANT_DIG;
|
||||
|
||||
// Check for NaN / infinity
|
||||
if (f_exp == 0xFF)
|
||||
{
|
||||
if (f_mant)
|
||||
{
|
||||
// NaN -> propagate mantissa and silence it
|
||||
uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
|
||||
h_mant |= 0x200;
|
||||
return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Infinity -> zero mantissa
|
||||
return (sign << 15) | CL_HALF_EXP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for zero
|
||||
if (!f_exp && !f_mant)
|
||||
{
|
||||
return (sign << 15);
|
||||
}
|
||||
|
||||
// Check for overflow
|
||||
if (exp >= CL_HALF_MAX_EXP)
|
||||
{
|
||||
return cl_half_handle_overflow(rounding_mode, sign);
|
||||
}
|
||||
|
||||
// Check for underflow
|
||||
if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
|
||||
{
|
||||
return cl_half_handle_underflow(rounding_mode, sign);
|
||||
}
|
||||
|
||||
// Check for value that will become denormal
|
||||
if (exp < -14)
|
||||
{
|
||||
// Denormal -> include the implicit 1 from the FP32 mantissa
|
||||
h_exp = 0;
|
||||
f_mant |= 1 << (CL_FLT_MANT_DIG - 1);
|
||||
|
||||
// Mantissa shift amount depends on exponent
|
||||
lsb_pos = -exp + (CL_FLT_MANT_DIG - 25);
|
||||
}
|
||||
|
||||
// Generate FP16 mantissa by shifting FP32 mantissa
|
||||
uint16_t h_mant = (uint16_t)(f_mant >> lsb_pos);
|
||||
|
||||
// Check whether we need to round
|
||||
uint32_t halfway = 1 << (lsb_pos - 1);
|
||||
uint32_t mask = (halfway << 1) - 1;
|
||||
switch (rounding_mode)
|
||||
{
|
||||
case CL_HALF_RTE:
|
||||
if ((f_mant & mask) > halfway)
|
||||
{
|
||||
// More than halfway -> round up
|
||||
h_mant += 1;
|
||||
}
|
||||
else if ((f_mant & mask) == halfway)
|
||||
{
|
||||
// Exactly halfway -> round to nearest even
|
||||
if (h_mant & 0x1)
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
case CL_HALF_RTZ:
|
||||
// Mantissa has already been truncated -> do nothing
|
||||
break;
|
||||
case CL_HALF_RTP:
|
||||
if ((f_mant & mask) && !sign)
|
||||
{
|
||||
// Round positive numbers up
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
case CL_HALF_RTN:
|
||||
if ((f_mant & mask) && sign)
|
||||
{
|
||||
// Round negative numbers down
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for mantissa overflow
|
||||
if (h_mant & 0x400)
|
||||
{
|
||||
h_exp += 1;
|
||||
h_mant = 0;
|
||||
}
|
||||
|
||||
return (sign << 15) | (h_exp << 10) | h_mant;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a cl_double to a cl_half.
|
||||
*/
|
||||
static inline cl_half cl_half_from_double(cl_double d, cl_half_rounding_mode rounding_mode)
|
||||
{
|
||||
// Type-punning to get direct access to underlying bits
|
||||
union
|
||||
{
|
||||
cl_double d;
|
||||
uint64_t i;
|
||||
} f64;
|
||||
f64.d = d;
|
||||
|
||||
// Extract sign bit
|
||||
uint16_t sign = f64.i >> 63;
|
||||
|
||||
// Extract FP64 exponent and mantissa
|
||||
uint64_t d_exp = (f64.i >> (CL_DBL_MANT_DIG - 1)) & 0x7FF;
|
||||
uint64_t d_mant = f64.i & (((uint64_t)1 << (CL_DBL_MANT_DIG - 1)) - 1);
|
||||
|
||||
// Remove FP64 exponent bias
|
||||
int64_t exp = d_exp - CL_DBL_MAX_EXP + 1;
|
||||
|
||||
// Add FP16 exponent bias
|
||||
uint16_t h_exp = (uint16_t)(exp + CL_HALF_MAX_EXP - 1);
|
||||
|
||||
// Position of the bit that will become the FP16 mantissa LSB
|
||||
uint32_t lsb_pos = CL_DBL_MANT_DIG - CL_HALF_MANT_DIG;
|
||||
|
||||
// Check for NaN / infinity
|
||||
if (d_exp == 0x7FF)
|
||||
{
|
||||
if (d_mant)
|
||||
{
|
||||
// NaN -> propagate mantissa and silence it
|
||||
uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
|
||||
h_mant |= 0x200;
|
||||
return (sign << 15) | CL_HALF_EXP_MASK | h_mant;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Infinity -> zero mantissa
|
||||
return (sign << 15) | CL_HALF_EXP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for zero
|
||||
if (!d_exp && !d_mant)
|
||||
{
|
||||
return (sign << 15);
|
||||
}
|
||||
|
||||
// Check for overflow
|
||||
if (exp >= CL_HALF_MAX_EXP)
|
||||
{
|
||||
return cl_half_handle_overflow(rounding_mode, sign);
|
||||
}
|
||||
|
||||
// Check for underflow
|
||||
if (exp < (CL_HALF_MIN_EXP - CL_HALF_MANT_DIG - 1))
|
||||
{
|
||||
return cl_half_handle_underflow(rounding_mode, sign);
|
||||
}
|
||||
|
||||
// Check for value that will become denormal
|
||||
if (exp < -14)
|
||||
{
|
||||
// Include the implicit 1 from the FP64 mantissa
|
||||
h_exp = 0;
|
||||
d_mant |= (uint64_t)1 << (CL_DBL_MANT_DIG - 1);
|
||||
|
||||
// Mantissa shift amount depends on exponent
|
||||
lsb_pos = (uint32_t)(-exp + (CL_DBL_MANT_DIG - 25));
|
||||
}
|
||||
|
||||
// Generate FP16 mantissa by shifting FP64 mantissa
|
||||
uint16_t h_mant = (uint16_t)(d_mant >> lsb_pos);
|
||||
|
||||
// Check whether we need to round
|
||||
uint64_t halfway = (uint64_t)1 << (lsb_pos - 1);
|
||||
uint64_t mask = (halfway << 1) - 1;
|
||||
switch (rounding_mode)
|
||||
{
|
||||
case CL_HALF_RTE:
|
||||
if ((d_mant & mask) > halfway)
|
||||
{
|
||||
// More than halfway -> round up
|
||||
h_mant += 1;
|
||||
}
|
||||
else if ((d_mant & mask) == halfway)
|
||||
{
|
||||
// Exactly halfway -> round to nearest even
|
||||
if (h_mant & 0x1)
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
case CL_HALF_RTZ:
|
||||
// Mantissa has already been truncated -> do nothing
|
||||
break;
|
||||
case CL_HALF_RTP:
|
||||
if ((d_mant & mask) && !sign)
|
||||
{
|
||||
// Round positive numbers up
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
case CL_HALF_RTN:
|
||||
if ((d_mant & mask) && sign)
|
||||
{
|
||||
// Round negative numbers down
|
||||
h_mant += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for mantissa overflow
|
||||
if (h_mant & 0x400)
|
||||
{
|
||||
h_exp += 1;
|
||||
h_mant = 0;
|
||||
}
|
||||
|
||||
return (sign << 15) | (h_exp << 10) | h_mant;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a cl_half to a cl_float.
|
||||
*/
|
||||
static inline cl_float cl_half_to_float(cl_half h)
|
||||
{
|
||||
// Type-punning to get direct access to underlying bits
|
||||
union
|
||||
{
|
||||
cl_float f;
|
||||
uint32_t i;
|
||||
} f32;
|
||||
|
||||
// Extract sign bit
|
||||
uint16_t sign = h >> 15;
|
||||
|
||||
// Extract FP16 exponent and mantissa
|
||||
uint16_t h_exp = (h >> (CL_HALF_MANT_DIG - 1)) & 0x1F;
|
||||
uint16_t h_mant = h & 0x3FF;
|
||||
|
||||
// Remove FP16 exponent bias
|
||||
int32_t exp = h_exp - CL_HALF_MAX_EXP + 1;
|
||||
|
||||
// Add FP32 exponent bias
|
||||
uint32_t f_exp = exp + CL_FLT_MAX_EXP - 1;
|
||||
|
||||
// Check for NaN / infinity
|
||||
if (h_exp == 0x1F)
|
||||
{
|
||||
if (h_mant)
|
||||
{
|
||||
// NaN -> propagate mantissa and silence it
|
||||
uint32_t f_mant = h_mant << (CL_FLT_MANT_DIG - CL_HALF_MANT_DIG);
|
||||
f_mant |= 0x400000;
|
||||
f32.i = (sign << 31) | 0x7F800000 | f_mant;
|
||||
return f32.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Infinity -> zero mantissa
|
||||
f32.i = (sign << 31) | 0x7F800000;
|
||||
return f32.f;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for zero / denormal
|
||||
if (h_exp == 0)
|
||||
{
|
||||
if (h_mant == 0)
|
||||
{
|
||||
// Zero -> zero exponent
|
||||
f_exp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Denormal -> normalize it
|
||||
// - Shift mantissa to make most-significant 1 implicit
|
||||
// - Adjust exponent accordingly
|
||||
uint32_t shift = 0;
|
||||
while ((h_mant & 0x400) == 0)
|
||||
{
|
||||
h_mant <<= 1;
|
||||
shift++;
|
||||
}
|
||||
h_mant &= 0x3FF;
|
||||
f_exp -= shift - 1;
|
||||
}
|
||||
}
|
||||
|
||||
f32.i = (sign << 31) | (f_exp << 23) | (h_mant << 13);
|
||||
return f32.f;
|
||||
}
|
||||
|
||||
|
||||
#undef CL_HALF_EXP_MASK
|
||||
#undef CL_HALF_MAX_FINITE_MAG
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* OPENCL_CL_HALF_H */
|
||||
+1294
File diff suppressed because it is too large
Load Diff
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
|
||||
*/
|
||||
|
||||
#ifndef OPENCL_CL_LAYER_H
|
||||
#define OPENCL_CL_LAYER_H
|
||||
|
||||
#include <CL/cl_icd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef cl_uint cl_layer_info;
|
||||
typedef cl_uint cl_layer_api_version;
|
||||
#define CL_LAYER_API_VERSION 0x4240
|
||||
#define CL_LAYER_API_VERSION_100 100
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetLayerInfo(cl_layer_info param_name,
|
||||
size_t param_value_size,
|
||||
void *param_value,
|
||||
size_t *param_value_size_ret);
|
||||
|
||||
typedef cl_int
|
||||
(CL_API_CALL *pfn_clGetLayerInfo)(cl_layer_info param_name,
|
||||
size_t param_value_size,
|
||||
void *param_value,
|
||||
size_t *param_value_size_ret);
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clInitLayer(cl_uint num_entries,
|
||||
const cl_icd_dispatch *target_dispatch,
|
||||
cl_uint *num_entries_ret,
|
||||
const cl_icd_dispatch **layer_dispatch_ret);
|
||||
|
||||
typedef cl_int
|
||||
(CL_API_CALL *pfn_clInitLayer)(cl_uint num_entries,
|
||||
const cl_icd_dispatch *target_dispatch,
|
||||
cl_uint *num_entries_ret,
|
||||
const cl_icd_dispatch **layer_dispatch_ret);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENCL_CL_LAYER_H */
|
||||
+1404
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_CL_VA_API_MEDIA_SHARING_INTEL_H
|
||||
#define __OPENCL_CL_VA_API_MEDIA_SHARING_INTEL_H
|
||||
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_platform.h>
|
||||
#include <va/va.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************
|
||||
* cl_intel_va_api_media_sharing extension *
|
||||
*******************************************/
|
||||
|
||||
#define cl_intel_va_api_media_sharing 1
|
||||
|
||||
/* error codes */
|
||||
#define CL_INVALID_VA_API_MEDIA_ADAPTER_INTEL -1098
|
||||
#define CL_INVALID_VA_API_MEDIA_SURFACE_INTEL -1099
|
||||
#define CL_VA_API_MEDIA_SURFACE_ALREADY_ACQUIRED_INTEL -1100
|
||||
#define CL_VA_API_MEDIA_SURFACE_NOT_ACQUIRED_INTEL -1101
|
||||
|
||||
/* cl_va_api_device_source_intel */
|
||||
#define CL_VA_API_DISPLAY_INTEL 0x4094
|
||||
|
||||
/* cl_va_api_device_set_intel */
|
||||
#define CL_PREFERRED_DEVICES_FOR_VA_API_INTEL 0x4095
|
||||
#define CL_ALL_DEVICES_FOR_VA_API_INTEL 0x4096
|
||||
|
||||
/* cl_context_info */
|
||||
#define CL_CONTEXT_VA_API_DISPLAY_INTEL 0x4097
|
||||
|
||||
/* cl_mem_info */
|
||||
#define CL_MEM_VA_API_MEDIA_SURFACE_INTEL 0x4098
|
||||
|
||||
/* cl_image_info */
|
||||
#define CL_IMAGE_VA_API_PLANE_INTEL 0x4099
|
||||
|
||||
/* cl_command_type */
|
||||
#define CL_COMMAND_ACQUIRE_VA_API_MEDIA_SURFACES_INTEL 0x409A
|
||||
#define CL_COMMAND_RELEASE_VA_API_MEDIA_SURFACES_INTEL 0x409B
|
||||
|
||||
typedef cl_uint cl_va_api_device_source_intel;
|
||||
typedef cl_uint cl_va_api_device_set_intel;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
|
||||
cl_platform_id platform,
|
||||
cl_va_api_device_source_intel media_adapter_type,
|
||||
void* media_adapter,
|
||||
cl_va_api_device_set_intel media_adapter_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id* devices,
|
||||
cl_uint* num_devices) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL * clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn)(
|
||||
cl_platform_id platform,
|
||||
cl_va_api_device_source_intel media_adapter_type,
|
||||
void* media_adapter,
|
||||
cl_va_api_device_set_intel media_adapter_set,
|
||||
cl_uint num_entries,
|
||||
cl_device_id* devices,
|
||||
cl_uint* num_devices) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
||||
clCreateFromVA_APIMediaSurfaceINTEL(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
VASurfaceID* surface,
|
||||
cl_uint plane,
|
||||
cl_int* errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_mem (CL_API_CALL * clCreateFromVA_APIMediaSurfaceINTEL_fn)(
|
||||
cl_context context,
|
||||
cl_mem_flags flags,
|
||||
VASurfaceID* surface,
|
||||
cl_uint plane,
|
||||
cl_int* errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueAcquireVA_APIMediaSurfacesINTEL(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
||||
clEnqueueReleaseVA_APIMediaSurfacesINTEL(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
typedef cl_int (CL_API_CALL *clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn)(
|
||||
cl_command_queue command_queue,
|
||||
cl_uint num_objects,
|
||||
const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list,
|
||||
cl_event* event) CL_API_SUFFIX__VERSION_1_2;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_CL_VA_API_MEDIA_SHARING_INTEL_H */
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018-2020 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __CL_VERSION_H
|
||||
#define __CL_VERSION_H
|
||||
|
||||
/* Detect which version to target */
|
||||
#if !defined(CL_TARGET_OPENCL_VERSION)
|
||||
#pragma message("cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 300 (OpenCL 3.0)")
|
||||
#define CL_TARGET_OPENCL_VERSION 300
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION != 100 && \
|
||||
CL_TARGET_OPENCL_VERSION != 110 && \
|
||||
CL_TARGET_OPENCL_VERSION != 120 && \
|
||||
CL_TARGET_OPENCL_VERSION != 200 && \
|
||||
CL_TARGET_OPENCL_VERSION != 210 && \
|
||||
CL_TARGET_OPENCL_VERSION != 220 && \
|
||||
CL_TARGET_OPENCL_VERSION != 300
|
||||
#pragma message("cl_version: CL_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120, 200, 210, 220, 300). Defaulting to 300 (OpenCL 3.0)")
|
||||
#undef CL_TARGET_OPENCL_VERSION
|
||||
#define CL_TARGET_OPENCL_VERSION 300
|
||||
#endif
|
||||
|
||||
|
||||
/* OpenCL Version */
|
||||
#if CL_TARGET_OPENCL_VERSION >= 300 && !defined(CL_VERSION_3_0)
|
||||
#define CL_VERSION_3_0 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 220 && !defined(CL_VERSION_2_2)
|
||||
#define CL_VERSION_2_2 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 210 && !defined(CL_VERSION_2_1)
|
||||
#define CL_VERSION_2_1 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 200 && !defined(CL_VERSION_2_0)
|
||||
#define CL_VERSION_2_0 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 120 && !defined(CL_VERSION_1_2)
|
||||
#define CL_VERSION_1_2 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 110 && !defined(CL_VERSION_1_1)
|
||||
#define CL_VERSION_1_1 1
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION >= 100 && !defined(CL_VERSION_1_0)
|
||||
#define CL_VERSION_1_0 1
|
||||
#endif
|
||||
|
||||
/* Allow deprecated APIs for older OpenCL versions. */
|
||||
#if CL_TARGET_OPENCL_VERSION <= 220 && !defined(CL_USE_DEPRECATED_OPENCL_2_2_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_2_2_APIS
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION <= 210 && !defined(CL_USE_DEPRECATED_OPENCL_2_1_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_2_1_APIS
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION <= 200 && !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION <= 120 && !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION <= 110 && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
|
||||
#endif
|
||||
#if CL_TARGET_OPENCL_VERSION <= 100 && !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS)
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_0_APIS
|
||||
#endif
|
||||
|
||||
#endif /* __CL_VERSION_H */
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008-2021 The Khronos Group Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __OPENCL_H
|
||||
#define __OPENCL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_gl.h>
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPENCL_H */
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+4
@@ -0,0 +1,4 @@
|
||||
These optional files (which are only needed when compiling with OpenCL support enabled in the encoder) are from the
|
||||
Khronos Group OpenCL headers github repo. They are Copyright (c) 2008-2020 The Khronos Group Inc.
|
||||
https://github.com/KhronosGroup/OpenCL-Headers
|
||||
|
||||
Vendored
+318
@@ -0,0 +1,318 @@
|
||||
# basis_universal
|
||||
Basis Universal Supercompressed GPU Texture Codec
|
||||
|
||||
<sub>(This software is available under a free and permissive license (Apache 2.0), but like many other large open source projects it needs financial support to sustain its continued security, bug fixes and improvements. In addition to maintenance and stability there are many desirable features and new interchange formats we would like to add. If your company is using Basis Universal in a product, please consider reaching out.)</sub>
|
||||
|
||||
Businesses: support continued development and maintenance via invoiced technical support, maintenance, or sponsoring contracts:
|
||||
<br> _E-mail: info @ binomial dot info_ or contact us on [Twitter](https://twitter.com/_binomial)
|
||||
|
||||
Also see the [Sponsors](https://github.com/BinomialLLC/basis_universal/wiki/Sponsors-and-Supporters) wiki page.
|
||||
|
||||
----
|
||||
|
||||
[](https://ci.appveyor.com/project/BinomialLLC/basis-universal)
|
||||
|
||||
Basis Universal is a ["supercompressed"](http://gamma.cs.unc.edu/GST/gst.pdf) GPU texture data interchange system that supports two highly compressed intermediate file formats (.basis or the [.KTX2 open standard from the Khronos Group](https://github.khronos.org/KTX-Specification/)) that can be quickly transcoded to a [very wide variety](https://github.com/BinomialLLC/basis_universal/wiki/OpenGL-texture-format-enums-table) of GPU compressed and uncompressed pixel formats: ASTC 4x4 L/LA/RGB/RGBA, PVRTC1 4bpp RGB/RGBA, PVRTC2 RGB/RGBA, BC7 mode 6 RGB, BC7 mode 5 RGB/RGBA, BC1-5 RGB/RGBA/X/XY, ETC1 RGB, ETC2 RGBA, ATC RGB/RGBA, ETC2 EAC R11 and RG11, FXT1 RGB, and uncompressed raster image formats 8888/565/4444.
|
||||
|
||||
The system now supports two modes: a high quality mode which is internally based off the [UASTC compressed texture format](https://richg42.blogspot.com/2020/01/uastc-block-format-encoding.html), and the original lower quality mode which is based off a subset of ETC1 called "ETC1S". UASTC is for extremely high quality (similar to BC7 quality) textures, and ETC1S is for very small files. The ETC1S system includes built-in data compression, while the UASTC system includes an optional Rate Distortion Optimization (RDO) post-process stage that conditions the encoded UASTC texture data in the .basis file so it can be more effectively LZ compressed by the end user. More technical details about UASTC integration are [here](https://github.com/BinomialLLC/basis_universal/wiki/UASTC-implementation-details).
|
||||
|
||||
Basis files support non-uniform texture arrays, so cubemaps, volume textures, texture arrays, mipmap levels, video sequences, or arbitrary texture "tiles" can be stored in a single file. The compressor is able to exploit color and pattern correlations across the entire file, so multiple images with mipmaps can be stored very efficiently in a single file.
|
||||
|
||||
The system's bitrate depends on the quality setting and image content, but common usable ETC1S bitrates are .3-1.25 bits/texel. ETC1S .basis files are typically 10-25% smaller than using RDO texture compression of the internal texture data stored in the .basis file followed by LZMA. For UASTC files, the bitrate is fixed at 8bpp, but with RDO post-processing and user-provided LZ compression on the .basis file the effective bitrate can be as low as 2bpp for video or for individual textures approximately 4-6bpp.
|
||||
|
||||
The .basis and .KTX2 transcoders have been fuzz tested using [zzuf](https://www.linux.com/news/fuzz-testing-zzuf).
|
||||
|
||||
So far, we've compiled the code using MSVC 2019, under Ubuntu 18.04 and 20 x64 using cmake with either clang 3.8 or gcc 5.4, and emscripten 1.35 to asm.js. (Be sure to use this version or later of emcc, as earlier versions fail with internal errors/exceptions during compilation.)
|
||||
|
||||
Basis Universal supports "skip blocks" in ETC1S compressed texture arrays, which makes it useful for basic [compressed texture video](http://gamma.cs.unc.edu/MPTC/) applications. Note that Basis Universal is still at heart a GPU texture compression system, not a dedicated video codec, so bitrates will be larger than even MPEG1.
|
||||
1/10/21 release notes:
|
||||
|
||||
For v1.13, we've added numerous ETC1S encoder optimizations designed to greatly speed up single threaded encoding time, as well as greatly reducing overall CPU utilization when multithreading is enabled. For benchmarking, we're using "-q 128 -no_multithreading -mip_fast". The encoder now uses approximately 1/3rd as much total CPU time for the same PSNR. The encoder can now optionally utilize SSE 4.1 - see the "-no_sse" command line option.
|
||||
|
||||
[Release Notes](https://github.com/BinomialLLC/basis_universal/wiki/Release-Notes)
|
||||
|
||||
### The first texture (and possibly image/video) compression codec developed without "Lena"
|
||||
|
||||
We retired Lena years ago. No testing is done with this image:
|
||||
|
||||
https://www.losinglena.com/
|
||||
|
||||
### Quick Introduction
|
||||
|
||||
Probably the most important concept to understand about Basis Universal before using it: The system supports **two** very different universal texture modes: The original "ETC1S" mode is low/medium quality, but the resulting file sizes are very small because the system has built-in compression for ETC1S texture format files. This is the command line encoding tool's default mode. ETC1S textures work best on images, photos, map data, or albedo/specular/etc. textures, but don't work as well on normal maps.
|
||||
|
||||
There's the second "UASTC" mode, which is significantly higher quality (comparable to BC7 and highest quality LDR ASTC 4x4), and is usable on all texture types including complex normal maps. UASTC mode purposely does not have built-in file compression like ETC1S mode does, so the resulting files are quite large (8-bits/texel - same as BC7) compared to ETC1S mode. The UASTC encoder has an optional Rate Distortion Optimization (RDO) encoding mode (implemented as a post-process over the encoded UASTC texture data), which conditions the output texture data in a way that results in better lossless compression when UASTC .basis files are compressed with Deflate/Zstd, etc. In UASTC mode, you must losslessly compress .basis files yourself. .KTX2 files have built-in lossless compression support using [Zstandard](https://facebook.github.io/zstd/), which is used by default on UASTC textures.
|
||||
|
||||
Basis Universal is not an image compression codec, but a GPU texture compression codec. It can be used just like an image compression codec, but that's not the only use case. Here's a [good intro](http://renderingpipeline.com/2012/07/texture-compression/) to GPU texture compression. If you're looking to primarily use the system as an image compression codec on sRGB photographic content, use the default ETC1S mode, because it has built-in compression.
|
||||
|
||||
**The "-q X" option controls the output quality in ETC1S mode.** The default is quality level 128. "-q 255" will increase quality quite a bit. If you want even higher quality, try "-max_selectors 16128 -max_endpoints 16128" instead of -q. -q internally tries to set the codebook sizes (or the # of quantization intervals for endpoints/selectors) for you. You need to experiment with the quality level on your content.
|
||||
|
||||
For tangent space normal maps, you should separate X into RGB and Y into Alpha, and provide the compressor with 32-bit/pixel input images. Or use the "-separate_rg_to_color_alpha" command line option which does this for you. The internal texture format that Basis Universal uses (ETC1S) doesn't handle tangent space normal maps encoded into RGB well. You need to separate the channels and recover Z in the pixel shader using z=sqrt(1-x^2-y^2).
|
||||
|
||||
### License and 3rd party code dependencies
|
||||
|
||||
Detailed legal, license, and IP information is [here](https://github.com/BinomialLLC/basis_universal/wiki/Legal-IP-License-Information). Basis Universal itself uses the Apache 2.0 licenses, but it also utilizes some optional BSD code (Zstandard). The supported texture formats are [open Khronos Group standards](https://www.khronos.org/registry/DataFormat/specs/1.1/dataformat.1.1.html).
|
||||
|
||||
All C/C++ code dependencies are present inside the Basis Universal repo itself to simplify building.
|
||||
|
||||
The encoder optionally uses Zstandard's single source file compressor (in zstd/zstd.c) to support compressing supercompressed KTX2 files. The stand-alone transcoder (in the "transcoder" directory) is a single .cpp source file library which has no 3rd party code dependencies apart from zstd/zstddeclib.c, which is also technically optional. It's only used for decompressing UASTC KTX2 files that use Zstandard.
|
||||
|
||||
### Command Line Compression Tool
|
||||
|
||||
The command line tool used to create, validate, and transcode/unpack .basis/.KTX2 files is named "basisu". Run basisu without any parameters for help.
|
||||
|
||||
The library and command line tool have no other 3rd party dependencies (that are not already in the repo), so it's pretty easy to build.
|
||||
|
||||
To build basisu (without SSE 4.1 support - the default):
|
||||
|
||||
```
|
||||
cmake CMakeLists.txt
|
||||
make
|
||||
```
|
||||
To build with SSE 4.1 support on x86/x64 systems (encoding is roughly 15-30% faster):
|
||||
```
|
||||
cmake -D SSE=TRUE CMakeLists.txt
|
||||
make
|
||||
```
|
||||
|
||||
For Visual Studio 2019, you can now either use the CMakeLists.txt file or the included `basisu.sln` file. Earlier versions of Visual Studio (particularly 2017) should work but aren't actively tested. We develop with the most up to date version of 2019.
|
||||
|
||||
To compress a sRGB PNG/BMP/TGA/JPEG image to an ETC1S .KTX2 file:
|
||||
|
||||
`basisu -ktx2 x.png`
|
||||
|
||||
To compress a sRGB PNG/BMP/TGA/JPEG image to an UASTC .KTX2 file:
|
||||
|
||||
`basisu -ktx2 -uastc x.png`
|
||||
|
||||
To compress a sRGB PNG/BMP/TGA/JPEG image to an RDO UASTC .KTX2 file with mipmaps:
|
||||
|
||||
`basisu -ktx2 -uastc -uastc_rdo_l 1.0 -mipmap x.png`
|
||||
|
||||
To compress a sRGB PNG/BMP/TGA/JPEG image to an ETC1S .basis file:
|
||||
|
||||
`basisu x.png`
|
||||
|
||||
To compress a image to a higher quality UASTC .basis file:
|
||||
|
||||
`basisu -uastc -uastc_level 2 x.png`
|
||||
|
||||
To compress a image to a higher quality UASTC .basis file with RDO post processing, so the .basis file is more compressible:
|
||||
|
||||
`basisu -uastc -uastc_level 2 -uastc_rdo_l .75 x.png`
|
||||
|
||||
-uastc_level X ranges from 0-4 and controls the UASTC encoder's performance vs. quality tradeoff. Level 0 is very fast, but low quality, level 2 is the default quality, while level 3 is the highest practical quality. Level 4 is impractically slow, but highest quality.
|
||||
|
||||
-uastc_rdo_l X controls the rate distortion stage's quality setting. The lower this value, the higher the quality, but the larger the compressed file size. Good values to try are between .2-3.0. The default is 1.0. RDO post-processing is currently pretty slow, but we'll be optimizing it over time.
|
||||
|
||||
UASTC texture video is supported and has been tested. In RDO mode with 7zip LZMA, we've seen average bitrates between 1-2 bpp. ETC1S mode is recommended for texture video, which gets bitrates around .25-.3 bpp.
|
||||
|
||||
Note that basisu defaults to sRGB colorspace metrics. If the input is a normal map, or some other type of non-sRGB (non-photographic) texture content, be sure to use -linear to avoid extra unnecessary artifacts. (Note: Currently, UASTC mode always uses linear colorspace metrics. sRGB and angulate metrics are comming soon.)
|
||||
|
||||
To add automatically generated mipmaps to the .basis file, at a higher than default quality level (which ranges from [1,255]):
|
||||
|
||||
`basisu -mipmap -q 190 x.png`
|
||||
|
||||
There are several mipmap options that allow you to change the filter kernel, the filter colorspace for the RGB channels (linear vs. sRGB), the smallest mipmap dimension, etc. The tool also supports generating cubemap files, 2D/cubemap texture arrays, etc.
|
||||
|
||||
To create a slightly higher quality ETC1S .basis file (one with better codebooks) at the default quality level (128) - note this is much slower to encode:
|
||||
|
||||
`basisu -comp_level 2 x.png`
|
||||
|
||||
On some rare images (ones with blue sky gradients come to bind), you may need to increase the ETC1S `-comp_level` setting. This controls the amount of overall effort the encoder uses to optimize the ETC1S codebooks (palettes) and compressed data stream. Higher comp_level's are *significantly* slower, and shouldn't be used unless necessary:
|
||||
|
||||
`basisu -ktx2 x.png -comp_level 5 -q 255`
|
||||
|
||||
Or try:
|
||||
`basisu -ktx2 x.png -comp_level 5 -max_endpoints 16128 -max_selectors 16128`
|
||||
|
||||
Note `-comp_level`'s 3-4 are almost as good as 5 and are a lot faster.
|
||||
|
||||
The compressor is multithreaded by default, but this can be disabled using the `-no_multithreading` command line option. The transcoder is currently single threaded although it supports multithreading decompression of multiple texture slices in parallel.
|
||||
|
||||
### Unpacking .basis/.KTX2 files to .PNG/.KTX files
|
||||
|
||||
You can either use the command line tool or [call the transcoder directly](https://github.com/BinomialLLC/basis_universal/wiki/How-to-Use-and-Configure-the-Transcoder) from JavaScript or C/C++ code to decompress .basis/.KTX2 files to GPU texture data or uncompressed images.
|
||||
|
||||
To use the command line tool to unpack a .basis or .KTX2 file to multiple .png/.ktx files:
|
||||
|
||||
`basisu x.basis`
|
||||
|
||||
Use the `-no_ktx` and `-etc1_only` options to unpack to less files. `-info` and `-validate` will just display file information and not output any files. The output .KTX1 files are currently in the KTX1 file format, not KTX2.
|
||||
|
||||
The mipmapped or cubemap .KTX files will be in a wide variety of compressed GPU texture formats (PVRTC1 4bpp, ETC1-2, BC1-5, BC7, etc.), and to my knowledge there is no single .KTX viewer tool that correctly and reliably supports every GPU texture format that we support. BC1-5 and BC7 files are viewable using AMD's Compressonator, ETC1/2 using Mali's Texture Compression Tool, and PVRTC1 using Imagination Tech's PVRTexTool. Links:
|
||||
|
||||
[Mali Texture Compression Tool](https://developer.arm.com/tools-and-software/graphics-and-gaming/graphics-development-tools/mali-texture-compression-tool)
|
||||
|
||||
[Compressonator](https://gpuopen.com/gaming-product/compressonator/)
|
||||
|
||||
[PVRTexTool](https://www.imgtec.com/developers/powervr-sdk-tools/pvrtextool/)
|
||||
|
||||
After compression, the compressor transcodes all slices in the output .basis file to validate that the file decompresses correctly. It also validates all header, compressed data, and slice data CRC16's.
|
||||
|
||||
For best quality, you must **supply basisu with original uncompressed source images**. Any other type of lossy compression applied before basisu (including ETC1/BC1-5, BC7, JPEG, etc.) will cause multi-generational artifacts to appear in the final output textures.
|
||||
|
||||
For the maximum possible achievable ETC1S mode quality with the current format and encoder (completely ignoring encoding speed!), use:
|
||||
|
||||
`basisu x.png -comp_level 5 -max_endpoints 16128 -max_selectors 16128 -no_selector_rdo -no_endpoint_rdo`
|
||||
|
||||
Level 5 is extremely slow, so unless you have a very powerful machine, levels 1-4 are recommended.
|
||||
|
||||
Note that "-no_selector_rdo -no_endpoint_rdo" are optional. Using them hurts rate distortion performance, but increases quality. An alternative is to use -selector_rdo_thresh X and -endpoint_rdo_thresh, with X ranging from [1,2] (higher=lower quality/better compression - see the tool's help text).
|
||||
|
||||
To compress small video sequences, say using tools like ffmpeg and VirtualDub:
|
||||
|
||||
`basisu -comp_level 2 -tex_type video -stats -debug -multifile_printf "pic%04u.png" -multifile_num 200 -multifile_first 1 -max_selectors 16128 -max_endpoints 16128 -endpoint_rdo_thresh 1.05 -selector_rdo_thresh 1.05`
|
||||
|
||||
For video, the more cores your machine has, the better. Basis is intended for smaller videos of a few dozen seconds or so. If you are very patient and have a Threadripper or Xeon workstation, you should be able to encode up to a few thousand 720P frames. The "webgl_videotest" directory contains a very simple video viewer.
|
||||
For texture video, use -comp_level 2 or 3. The default is 1, which isn't quite good enough for texture video. Higher comp_level's result in reduced ETC1S artifacts.
|
||||
|
||||
The .basis file will contain multiple images (all using the same global codebooks), which you can retrieve using the transcoder's image API. The system now supports [conditional replenisment](https://en.wikipedia.org/wiki/MPEG-1) (CR, or "skip blocks"). CR can reduce the bitrate of some videos (highly dependent on how dynamic the content is) by over 50%. For videos using CR, the images must be requested from the transcoder in sequence from first to last, and random access is only allowed to I-Frames.
|
||||
|
||||
If you are doing rate distortion comparisons vs. other similar systems, be sure to experiment with increasing the endpoint RDO threshold (-endpoint_rdo_thresh X). This setting controls how aggressively the compressor's backend will combine together nearby blocks so they use the same block endpoint codebook vectors, for better coding efficiency. X defaults to a modest 1.5, which means the backend is allowed to increase the overall color distance by 1.5x while searching for merge candidates. The higher this setting, the better the compression, with the tradeoff of more block artifacts. Settings up to ~2.25 can work well, and make the codec more competitive. "-endpoint_rdo_thresh 1.75" is a good setting on many textures.
|
||||
|
||||
For video, level 1 should result in decent results on most clips. For less banding, level 2 can make a big difference. This is still an active area of development, and quality/encoding perf. will improve over time.
|
||||
|
||||
To control the ETC1S encoder's quality vs. encoding speed tradeoff, see [ETC1S Compression Effort Levels](https://github.com/BinomialLLC/basis_universal/wiki/ETC1S-Compression-Effort-Levels).
|
||||
|
||||
### More Examples
|
||||
|
||||
`basisu x.png`\
|
||||
Compress sRGB image x.png to a ETC1S format x.basis file using default settings (multiple filenames OK). ETC1S format files are typically very small on disk (around .5-1.5 bits/texel).
|
||||
|
||||
`basisu -uastc x.png`\
|
||||
Compress image x.png to a UASTC format x.basis file using default settings (multiple filenames OK). UASTC files are the same size as BC7 on disk (8-bpp). Be sure to compress UASTC .basis files yourself using Deflate, zstd, etc. To increase .basis file compressibility (trading off quality for smaller compressed files) use the "-uastc_rdo_q X" command line parameter.
|
||||
|
||||
`basisu -q 255 x.png`\
|
||||
Compress sRGB image x.png to x.basis at max quality level achievable without manually setting the codebook sizes (multiple filenames OK)
|
||||
|
||||
`basisu x.basis`\
|
||||
Unpack x.basis to PNG/KTX files (multiple filenames OK)
|
||||
|
||||
`basisu -validate -file x.basis`\
|
||||
Validate x.basis (check header, check file CRC's, attempt to transcode all slices)
|
||||
|
||||
`basisu -unpack -file x.basis`\
|
||||
Validates, transcodes and unpacks x.basis to mipmapped .KTX and RGB/A .PNG files (transcodes to all supported GPU texture formats)
|
||||
|
||||
`basisu -q 255 -file x.png -mipmap -debug -stats`\
|
||||
Compress sRGB x.png to x.basis at quality level 255 with compressor debug output/statistics
|
||||
|
||||
`basisu -linear -max_endpoints 16128 -max_selectors 16128 -file x.png`\
|
||||
Compress non-sRGB x.png to x.basis using the largest supported manually specified codebook sizes
|
||||
|
||||
`basisu -linear -global_sel_pal -no_hybrid_sel_cb -file x.png`\
|
||||
Compress a non-sRGB image, use virtual selector codebooks for improved compression (but slower encoding)
|
||||
|
||||
`basisu -linear -global_sel_pal -file x.png`\
|
||||
Compress a non-sRGB image, use hybrid selector codebooks for slightly improved compression (but slower encoding)
|
||||
|
||||
`basisu -tex_type video -comp_level 2 -framerate 20 -multifile_printf "x%02u.png" -multifile_first 1 -multifile_count 20 -selector_rdo_thresh 1.05 -endpoint_rdo_thresh 1.05`\
|
||||
Compress a 20 sRGB source image video sequence (x01.png, x02.png, x03.png, etc.) to x01.basis
|
||||
|
||||
`basisu -comp_level 2 -q 255 -file x.png -mipmap -y_flip`\
|
||||
Compress a mipmapped x.basis file from an sRGB image named x.png, Y flip each source image, set encoder to level 2 for slightly higher quality (but slower encoding).
|
||||
|
||||
### WebGL test
|
||||
|
||||
The "WebGL" directory contains three simple WebGL demos that use the transcoder and compressor compiled to wasm with [emscripten](https://emscripten.org/). See more details [here](webgl/README.md).
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
### Installation using the vcpkg dependency manager
|
||||
|
||||
You can download and install Basis Universal using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install basisu
|
||||
|
||||
The Basis Universal port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
### 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 compressor when compiled with emscripten. A simple Web compression demo is in webgl/encode_test. All compressor features, including texture video, are supported and fully exposed.
|
||||
|
||||
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.
|
||||
|
||||
### Low-level C++ encoder API
|
||||
|
||||
You can call the encoder directly, instead of using the command line tool. We'll be adding documentation and some examples by the end of the year. For now, some important notes:
|
||||
|
||||
First, ALWAYS call ```basisu::basisu_encoder_init()``` to initialize the library. Otherwise, you'll get undefined behavior or black textures.
|
||||
|
||||
Create a job pool, fill in the ```basis_compress_params``` struct, then call ```basisu::basis_compressor::init()```, then ```basisu::basis_compressor::process()```. Like this for UASTC:
|
||||
|
||||
```
|
||||
bool test()
|
||||
{
|
||||
basisu_encoder_init();
|
||||
|
||||
image img;
|
||||
if (!load_image("test.png", img))
|
||||
{
|
||||
printf("Can't load image\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
basis_compressor_params basisCompressorParams;
|
||||
|
||||
basisCompressorParams.m_source_images.push_back(img);
|
||||
basisCompressorParams.m_perceptual = false;
|
||||
basisCompressorParams.m_mip_srgb = false;
|
||||
|
||||
basisCompressorParams.m_write_output_basis_files = true;
|
||||
basisCompressorParams.m_out_filename = "test.basis";
|
||||
|
||||
basisCompressorParams.m_uastc = true;
|
||||
basisCompressorParams.m_rdo_uastc_multithreading = false;
|
||||
basisCompressorParams.m_multithreading = false;
|
||||
basisCompressorParams.m_debug = true;
|
||||
basisCompressorParams.m_status_output = true;
|
||||
basisCompressorParams.m_compute_stats = true;
|
||||
|
||||
basisu::job_pool jpool(1);
|
||||
basisCompressorParams.m_pJob_pool = &jpool;
|
||||
|
||||
basisu::basis_compressor basisCompressor;
|
||||
basisu::enable_debug_printf(true);
|
||||
|
||||
bool ok = basisCompressor.init(basisCompressorParams);
|
||||
if (ok)
|
||||
{
|
||||
basisu::basis_compressor::error_code result = basisCompressor.process();
|
||||
|
||||
if (result == basisu::basis_compressor::cECSuccess)
|
||||
printf("Success\n");
|
||||
else
|
||||
{
|
||||
printf("Failure\n");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Failure\n");
|
||||
return ok;
|
||||
}
|
||||
```
|
||||
|
||||
The command line tool uses this API too, so you can always look at that to see what it does given a set of command line options.
|
||||
|
||||
### Repository Licensing with REUSE
|
||||
|
||||
The repository has been updated to be compliant with the REUSE licenese
|
||||
checking tool (https://reuse.software/). This was done by adding the complete
|
||||
text of all licenses used under the LICENSES/ directory and adding the
|
||||
.reuse/dep5 file which specifies licenses for files which don't contain
|
||||
them in a form which can be automatically parse by the reuse tool. REUSE
|
||||
does not alter copyrights or licenses, simply captures information about
|
||||
licensing to ensure the entire repository has explicit licensing information.
|
||||
|
||||
To ensure continued REUSE compliance, run `reuse lint` at the root of
|
||||
a clean, checked-out repository periodically, or run it during CI tests
|
||||
before any build artifacts have been created.
|
||||
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
---
|
||||
|
||||
image:
|
||||
- macos
|
||||
- Ubuntu2004
|
||||
- Visual Studio 2019
|
||||
|
||||
configuration: Release
|
||||
|
||||
environment:
|
||||
APPVEYOR_YML_DISABLE_PS_LINUX: true
|
||||
|
||||
install:
|
||||
- sh: |
|
||||
if [ "$(uname)" != "Darwin" ]; then
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y dos2unix recode
|
||||
fi
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
New-Item -Path . -Name "build" -ItemType "directory"
|
||||
cd build
|
||||
cmake --version
|
||||
cmake ../ -DCMAKE_BUILD_TYPE:STRING="$env:CONFIGURATION"
|
||||
cmake --build . --config $env:CONFIGURATION
|
||||
cd ../
|
||||
- sh: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake --version
|
||||
cmake ../ -DCMAKE_BUILD_TYPE:STRING="${CONFIGURATION}"
|
||||
cmake --build . --config ${CONFIGURATION}
|
||||
cd ../
|
||||
|
||||
test_script:
|
||||
- sh: |
|
||||
if [ "$(uname)" != "Darwin" ]; then
|
||||
bash ./format.sh
|
||||
fi
|
||||
|
||||
artifacts:
|
||||
# Linux
|
||||
- path: bin/basisu
|
||||
# MacOS
|
||||
- path: bin_osx/basisu
|
||||
# Windows
|
||||
- path: bin\$(configuration)\basisu.exe
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28803.202
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basisu", "basisu.vcxproj", "{59586A07-8E7E-411D-BC3D-387E039AA423}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Debug|x64.Build.0 = Debug|x64
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Debug|x86.Build.0 = Debug|Win32
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Release|x64.ActiveCfg = Release|x64
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Release|x64.Build.0 = Release|x64
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Release|x86.ActiveCfg = Release|Win32
|
||||
{59586A07-8E7E-411D-BC3D-387E039AA423}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5E583429-7830-4B3A-9DDE-F01B115CE0D8}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Vendored
+234
@@ -0,0 +1,234 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{59586A07-8E7E-411D-BC3D-387E039AA423}</ProjectGuid>
|
||||
<RootNamespace>basisu</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
<TargetName>$(ProjectName)D</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<AdditionalIncludeDirectories>OpenCL</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);BASISU_SUPPORT_SSE=1;BASISU_SUPPORT_OPENCL=1</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>OpenCL</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);BASISU_SUPPORT_SSE=1;BASISU_SUPPORT_OPENCL=1</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<AdditionalIncludeDirectories>OpenCL</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions);BASISU_SUPPORT_SSE=1;BASISU_SUPPORT_OPENCL=1</PreprocessorDefinitions>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>OpenCL</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions);BASISU_SUPPORT_SSE=1;BASISU_SUPPORT_OPENCL=1</PreprocessorDefinitions>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="encoder\basisu_backend.cpp" />
|
||||
<ClCompile Include="encoder\basisu_basis_file.cpp" />
|
||||
<ClCompile Include="encoder\basisu_bc7enc.cpp" />
|
||||
<ClCompile Include="encoder\basisu_comp.cpp" />
|
||||
<ClCompile Include="encoder\basisu_enc.cpp" />
|
||||
<ClCompile Include="encoder\basisu_etc.cpp" />
|
||||
<ClCompile Include="encoder\basisu_frontend.cpp" />
|
||||
<ClCompile Include="encoder\basisu_gpu_texture.cpp" />
|
||||
<ClCompile Include="encoder\basisu_kernels_sse.cpp" />
|
||||
<ClCompile Include="encoder\basisu_opencl.cpp" />
|
||||
<ClCompile Include="encoder\basisu_pvrtc1_4.cpp" />
|
||||
<ClCompile Include="encoder\basisu_resampler.cpp" />
|
||||
<ClCompile Include="encoder\basisu_resample_filters.cpp" />
|
||||
<ClCompile Include="encoder\basisu_ssim.cpp" />
|
||||
<ClCompile Include="encoder\basisu_uastc_enc.cpp" />
|
||||
<ClCompile Include="encoder\jpgd.cpp" />
|
||||
<ClCompile Include="encoder\pvpngreader.cpp" />
|
||||
<ClCompile Include="zstd\zstd.c" />
|
||||
<ClInclude Include="encoder\basisu_ocl_kernels.h" />
|
||||
<ClInclude Include="encoder\basisu_opencl.h" />
|
||||
<ClInclude Include="encoder\pvpngreader.h" />
|
||||
<ClInclude Include="transcoder\basisu_containers_impl.h" />
|
||||
<ClCompile Include="transcoder\basisu_transcoder.cpp" />
|
||||
<ClInclude Include="encoder\basisu_backend.h" />
|
||||
<ClInclude Include="encoder\basisu_basis_file.h" />
|
||||
<ClInclude Include="encoder\basisu_bc7enc.h" />
|
||||
<ClInclude Include="encoder\basisu_comp.h" />
|
||||
<ClInclude Include="encoder\basisu_enc.h" />
|
||||
<ClInclude Include="encoder\basisu_etc.h" />
|
||||
<ClInclude Include="encoder\basisu_frontend.h" />
|
||||
<ClInclude Include="encoder\basisu_gpu_texture.h" />
|
||||
<ClInclude Include="encoder\basisu_kernels_declares.h" />
|
||||
<ClInclude Include="encoder\basisu_kernels_imp.h" />
|
||||
<ClInclude Include="encoder\basisu_miniz.h" />
|
||||
<ClInclude Include="encoder\basisu_pvrtc1_4.h" />
|
||||
<ClInclude Include="encoder\basisu_resampler.h" />
|
||||
<ClInclude Include="encoder\basisu_resampler_filters.h" />
|
||||
<ClInclude Include="encoder\basisu_ssim.h" />
|
||||
<ClInclude Include="encoder\basisu_uastc_enc.h" />
|
||||
<ClInclude Include="encoder\cppspmd_flow.h" />
|
||||
<ClInclude Include="encoder\cppspmd_math.h" />
|
||||
<ClInclude Include="encoder\cppspmd_math_declares.h" />
|
||||
<ClInclude Include="encoder\cppspmd_sse.h" />
|
||||
<ClInclude Include="encoder\cppspmd_type_aliases.h" />
|
||||
<ClInclude Include="encoder\jpgd.h" />
|
||||
<ClInclude Include="transcoder\basisu.h" />
|
||||
<ClInclude Include="transcoder\basisu_containers.h" />
|
||||
<ClInclude Include="transcoder\basisu_file_headers.h" />
|
||||
<ClInclude Include="transcoder\basisu_transcoder.h" />
|
||||
<ClInclude Include="transcoder\basisu_transcoder_internal.h" />
|
||||
<ClInclude Include="transcoder\basisu_transcoder_uastc.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="basisu_tool.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="bin\ocl_kernels.cl" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_astc.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_astc_0_255.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_atc_55.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_atc_56.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_bc7_m5_alpha.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_bc7_m5_color.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_dxt1_5.inc" />
|
||||
<None Include="transcoder\basisu_transcoder_tables_dxt1_6.inc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="basisu_tool.cpp" />
|
||||
<ClCompile Include="transcoder\basisu_transcoder.cpp">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_backend.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_basis_file.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_bc7enc.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_comp.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_enc.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_etc.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_frontend.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_gpu_texture.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_pvrtc1_4.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_resampler.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_uastc_enc.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\jpgd.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_resample_filters.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_ssim.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_kernels_sse.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="zstd\zstd.c">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\basisu_opencl.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="encoder\pvpngreader.cpp">
|
||||
<Filter>encoder</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="transcoder\basisu.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_transcoder_internal.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_transcoder.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_transcoder_uastc.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_backend.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_basis_file.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_bc7enc.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_comp.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_enc.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_etc.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_frontend.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_gpu_texture.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_miniz.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_pvrtc1_4.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_resampler.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_uastc_enc.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\jpgd.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_ssim.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_resampler_filters.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_kernels_declares.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_kernels_imp.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\cppspmd_flow.h">
|
||||
<Filter>encoder\cppspmd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\cppspmd_math.h">
|
||||
<Filter>encoder\cppspmd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\cppspmd_math_declares.h">
|
||||
<Filter>encoder\cppspmd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\cppspmd_sse.h">
|
||||
<Filter>encoder\cppspmd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\cppspmd_type_aliases.h">
|
||||
<Filter>encoder\cppspmd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_containers.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_containers_impl.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transcoder\basisu_file_headers.h">
|
||||
<Filter>transcoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_opencl.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\basisu_ocl_kernels.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="encoder\pvpngreader.h">
|
||||
<Filter>encoder</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="transcoder\basisu_transcoder_tables_dxt1_6.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_dxt1_5.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_astc.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_astc_0_255.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_bc7_m5_alpha.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_bc7_m5_color.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_atc_55.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="transcoder\basisu_transcoder_tables_atc_56.inc">
|
||||
<Filter>transcoder</Filter>
|
||||
</None>
|
||||
<None Include="bin\ocl_kernels.cl">
|
||||
<Filter>encoder</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="transcoder">
|
||||
<UniqueIdentifier>{7a54aaad-1d10-4bdf-b8e9-c14ed2263ed8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="encoder">
|
||||
<UniqueIdentifier>{518dd5c5-a7e1-4e79-8bb4-253e2d540c2c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="encoder\cppspmd">
|
||||
<UniqueIdentifier>{ab12ac82-9c39-494d-a36b-129dd1b2dec5}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Vendored
+4489
File diff suppressed because it is too large
Load Diff
+1290
File diff suppressed because it is too large
Load Diff
Vendored
+1
@@ -0,0 +1 @@
|
||||
executable files go here
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
cmake -D CMAKE_C_COMPILER=/usr/bin/clang -D CMAKE_CXX_COMPILER=/usr/bin/clang++ .
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
if ! emcc --version
|
||||
then
|
||||
echo "Emscripten not found on PATH. Please follow instructions on https://emscripten.org/docs/getting_started/downloads.html"
|
||||
exit
|
||||
fi
|
||||
|
||||
emcmake cmake .
|
||||
emcmake make
|
||||
@@ -0,0 +1,2 @@
|
||||
# Mac finder
|
||||
.DS_Store
|
||||
@@ -0,0 +1,3 @@
|
||||
# Single File Basis Universal Transcoder
|
||||
|
||||
Header and implementation generated using the [single file transcoder](../../single_file_transcoder) post-process script. Unlike the examples in that subproject here the transcoder header was kept as a seperate file (using the `-k` option, see the [README](../../single_file_transcoder/README.md)).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
# Windows intermediate files
|
||||
bin/x86/
|
||||
bin/x64/
|
||||
|
||||
# VS project files
|
||||
*.vcxproj.user
|
||||
.vs/
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.sdf
|
||||
*.suo
|
||||
*.opensdf
|
||||
*.aps
|
||||
@@ -0,0 +1,7 @@
|
||||
# Windows Previewers for Basis Universal
|
||||
|
||||
Build using Visual Studio from 2012 onwards. Enable from an Administrator console using `regsvr32 previewers.dll` (and remove using `regsvr32 /u previewers.dll`).
|
||||
|
||||

|
||||
|
||||
Work-in-progress. Prebuilt signed version and installer coming soon. Mac version to follow.
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "basisthumbprovider.h"
|
||||
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "basisu_transcoder.cpp"
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
using namespace basist;
|
||||
|
||||
BasisThumbProvider::BasisThumbProvider() : count(1), stream(NULL) {
|
||||
dprintf("BasisThumbProvider ctor");
|
||||
basisu_transcoder_init();
|
||||
}
|
||||
|
||||
BasisThumbProvider::~BasisThumbProvider() {
|
||||
dprintf("BasisThumbProvider **dtor**");
|
||||
if (stream) {
|
||||
stream->Release();
|
||||
stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHODIMP BasisThumbProvider::QueryInterface(REFIID riid, void **ppv) {
|
||||
static const QITAB qit[] = {
|
||||
QITABENT(BasisThumbProvider, IThumbnailProvider),
|
||||
QITABENT(BasisThumbProvider, IInitializeWithStream),
|
||||
{0},
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) BasisThumbProvider::AddRef() {
|
||||
return InterlockedIncrement(&count);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) BasisThumbProvider::Release() {
|
||||
LONG refs = InterlockedDecrement(&count);
|
||||
if (refs == 0) {
|
||||
delete this;
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP BasisThumbProvider::Initialize(IStream *pStream, DWORD grfMode) {
|
||||
dprintf("BasisThumbProvider::Initialize");
|
||||
HRESULT hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
||||
if (!stream) {
|
||||
hr = pStream->QueryInterface(&stream);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Note: thumbnails get written here: %LocalAppData%\Microsoft\Windows\Explorer
|
||||
IFACEMETHODIMP BasisThumbProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) {
|
||||
STATSTG stat;
|
||||
if (stream && SUCCEEDED(stream->Stat(&stat, STATFLAG_NONAME))) {
|
||||
if (void* data = malloc(static_cast<size_t>(stat.cbSize.LowPart))) {
|
||||
ULONG size = 0;
|
||||
if (SUCCEEDED(stream->Read(data, static_cast<ULONG>(stat.cbSize.LowPart), &size))) {
|
||||
if (size == stat.cbSize.LowPart) {
|
||||
basisu_transcoder transcoder;
|
||||
if (transcoder.validate_header(data, size)) {
|
||||
dprintf("Requested %d bytes for %dx%d image", size, cx, cx);
|
||||
basisu_image_info info;
|
||||
if (transcoder.get_image_info(data, size, info, 0)) {
|
||||
uint32_t level = 0;
|
||||
uint32_t descW = 0, descH = 0, blocks;
|
||||
for (uint32_t n = 0; n < info.m_total_levels; n++) {
|
||||
if (transcoder.get_image_level_desc(data, size, 0, n, descW, descH, blocks)) {
|
||||
dprintf("mipmap level w: %d, h: %d (blocks: %d)", descW, descH, blocks);
|
||||
if (cx >= std::max(descW, descH)) {
|
||||
level = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
basisu_file_info fileInfo;
|
||||
transcoder.get_file_info(data, size, fileInfo);
|
||||
if (transcoder.start_transcoding(data, size)) {
|
||||
uint32_t bytes = basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format::cTFRGBA32) * descW * descH;
|
||||
dprintf("Started transcode (%dx%d @ %d bytes)", descW, descH, bytes);
|
||||
if (void* rgbBuf = malloc(bytes)) {
|
||||
// Note: the API expects total pixels here instead of blocks for cTFRGBA32
|
||||
if (transcoder.transcode_image_level(data, size, 0, level, rgbBuf, descW * descH, transcoder_texture_format::cTFRGBA32)) {
|
||||
dprintf("Decoded!!!!");
|
||||
*phbmp = rgbToBitmap(static_cast<uint32_t*>(rgbBuf), descW, descH, fileInfo.m_y_flipped);
|
||||
}
|
||||
delete rgbBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
return (*phbmp) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
//********************************** Factory *********************************/
|
||||
|
||||
BasisThumbProviderFactory::BasisThumbProviderFactory() : count(1) {}
|
||||
|
||||
BasisThumbProviderFactory::~BasisThumbProviderFactory() {}
|
||||
|
||||
IFACEMETHODIMP BasisThumbProviderFactory::QueryInterface(REFIID riid, void **ppv) {
|
||||
static const QITAB qit[] = {
|
||||
QITABENT(BasisThumbProviderFactory, IClassFactory),
|
||||
{0},
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) BasisThumbProviderFactory::AddRef() {
|
||||
return InterlockedIncrement(&count);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) BasisThumbProviderFactory::Release() {
|
||||
LONG refs = InterlockedDecrement(&count);
|
||||
if (refs == 0) {
|
||||
delete this;
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP BasisThumbProviderFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) {
|
||||
HRESULT hr = CLASS_E_NOAGGREGATION;
|
||||
if (pUnkOuter == NULL) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
if (BasisThumbProvider* provider = new (std::nothrow) BasisThumbProvider()) {
|
||||
hr = provider->QueryInterface(riid, ppv);
|
||||
provider->Release();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP BasisThumbProviderFactory::LockServer(BOOL fLock) {
|
||||
if (fLock) {
|
||||
InterlockedIncrement(&count);
|
||||
} else {
|
||||
InterlockedDecrement(&count);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <thumbcache.h>
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class BasisThumbProvider : public IInitializeWithStream, public IThumbnailProvider
|
||||
{
|
||||
public:
|
||||
BasisThumbProvider();
|
||||
// IUnknown::QueryInterface()
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) override;
|
||||
// IUnknown::AddRef()
|
||||
IFACEMETHODIMP_(ULONG) AddRef() override;
|
||||
// IUnknown::Release()
|
||||
IFACEMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IInitializeWithStream::Initialize()
|
||||
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode) override;
|
||||
|
||||
// IThumbnailProvider::GetThumbnail()
|
||||
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) override;
|
||||
|
||||
protected:
|
||||
virtual ~BasisThumbProvider();
|
||||
|
||||
private:
|
||||
LONG count;
|
||||
IStream* stream;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class BasisThumbProviderFactory : public IClassFactory
|
||||
{
|
||||
public:
|
||||
BasisThumbProviderFactory();
|
||||
// IUnknown::QueryInterface()
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) override;
|
||||
// IUnknown::AddRef()
|
||||
IFACEMETHODIMP_(ULONG) AddRef() override;
|
||||
// IUnknown::Release()
|
||||
IFACEMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IClassFactory::CreateInstance()
|
||||
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) override;
|
||||
// IClassFactory::LockServer()
|
||||
IFACEMETHODIMP LockServer(BOOL fLock) override;
|
||||
|
||||
protected:
|
||||
virtual ~BasisThumbProviderFactory();
|
||||
|
||||
private:
|
||||
LONG count;
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "helpers.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
void dprintf(char* const fmt, ...) {
|
||||
#ifdef _DEBUG
|
||||
va_list args;
|
||||
char buf[256];
|
||||
va_start(args, fmt);
|
||||
int len = vsnprintf_s(buf, sizeof buf, fmt, args);
|
||||
va_end (args);
|
||||
if (len > 0) {
|
||||
buf[sizeof buf - 1] = 0;
|
||||
OutputDebugStringA(buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HBITMAP rgbToBitmap(const uint32_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip) {
|
||||
/*
|
||||
* Creates a bitmap (a DIB) for the passed-in pixel size. Note that
|
||||
* negation of the height means top-down, origin upper-left, which is the
|
||||
* regular case.
|
||||
*
|
||||
* TODO: 16-bit variant instead?
|
||||
*/
|
||||
assert(src && imgW && imgH);
|
||||
BITMAPINFO bmi = {
|
||||
sizeof(bmi.bmiHeader)
|
||||
};
|
||||
bmi.bmiHeader.biWidth = imgW;
|
||||
bmi.bmiHeader.biHeight = (flip) ? imgH : -static_cast<int32_t>(imgH);
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
void* pixels = NULL;
|
||||
HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &pixels, NULL, 0);
|
||||
/*
|
||||
* RGBA to BGRA conversion.
|
||||
*
|
||||
* Note: we keep the alpha.
|
||||
*/
|
||||
if (hbmp && pixels) {
|
||||
uint32_t* dst = static_cast<uint32_t*>(pixels);
|
||||
for (unsigned xy = imgW * imgH; xy > 0; xy--) {
|
||||
uint32_t rgba = *src++;
|
||||
*dst++ = ((rgba & 0x000000FF) << 16)
|
||||
| ((rgba & 0xFF00FF00) )
|
||||
| ((rgba & 0x00FF0000) >> 16);
|
||||
}
|
||||
GdiFlush();
|
||||
}
|
||||
return hbmp;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* Write a formatted string to the connected debugger (e.g. DebugView).
|
||||
*
|
||||
* \param[in] fmt content to write in \c printf format (followed by optional arguments)
|
||||
*/
|
||||
void dprintf(char* const fmt, ...);
|
||||
|
||||
/**
|
||||
* Converts raw RGBA data to a Windows BGRA bitmap.
|
||||
*
|
||||
* \param[in] src raw RGBA data
|
||||
* \param[in] imgW width of the decoded image
|
||||
* \param[in] imgH height of the decoded image
|
||||
* \return handle to a bitmap (ownership passed to the caller)
|
||||
*/
|
||||
HBITMAP rgbToBitmap(const uint32_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip = false);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 624 KiB |
@@ -0,0 +1,118 @@
|
||||
#include <Windows.h>
|
||||
#include <ShlObj.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "basisthumbprovider.h"
|
||||
|
||||
#define SHELLEX_THUMBNAIL_CLSID _T("ShellEx\\{E357FCCD-A995-4576-B01F-234630154E96}")
|
||||
#define SHELLEX_PREVIEWER_CLSID _T("ShellEx\\{8895B1C6-B41F-4C1C-A562-0D564250836F}")
|
||||
|
||||
#define THUMBNAIL_HANDLER_TITLE _T("Basis Thumbnail Handler")
|
||||
#define THUMBNAIL_HANDLER_CLSID _T("{CD1F0EA0-283C-4D90-A41D-DEBD9207D91F}")
|
||||
|
||||
#define PREVIEWER_HANDLER_TITLE _T("Basis Previewer Handler")
|
||||
#define PREVIEWER_HANDLER_CLSID _T("{7B5DA275-3BB6-45AE-B0EB-E50187A28F13}")
|
||||
|
||||
#define FILE_EXTENSION _T(".basis")
|
||||
|
||||
static const CLSID CLSID_ThumbnailHandler = {0xCD1F0EA0, 0x283C, 0x4D90, {0xA4, 0x1D, 0xDE, 0xBD, 0x92, 0x07, 0xD9, 0x1F}};
|
||||
static const CLSID CLSID_PreviewerHandler = {0x7B5DA275, 0x3BB6, 0x45AE, {0xB0, 0xEB, 0xE5, 0x01, 0x87, 0xA2, 0x8F, 0x13}};
|
||||
|
||||
static TCHAR dllPath[MAX_PATH] = {0};
|
||||
|
||||
static LONG dllRefs = 0;
|
||||
|
||||
#ifndef BAIL_ON_FAIL
|
||||
#define BAIL_ON_FAIL(code) if (FAILED((hr = (code)))) return hr
|
||||
#endif
|
||||
|
||||
static HRESULT setRegKey(HKEY root, LPTSTR key, LPTSTR val, LPTSTR data) {
|
||||
HKEY hKey;
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyEx(root, key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL));
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, val, 0, REG_SZ, reinterpret_cast<LPBYTE>(data), static_cast<DWORD>(_tcslen(data) * sizeof TCHAR)));
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hInstDLL, DWORD reason, LPVOID /*reserved*/) {
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
OutputDebugString(_T("DllMain"));
|
||||
if (GetModuleFileName(hInstDLL, dllPath, sizeof dllPath) == 0) {
|
||||
#ifdef _DEBUG
|
||||
OutputDebugString(_T("Failed to obtain DLL path"));
|
||||
#endif
|
||||
}
|
||||
DisableThreadLibraryCalls(hInstDLL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) {
|
||||
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||
if (IsEqualCLSID(CLSID_ThumbnailHandler, rclsid)) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
if (IClassFactory* factory = new (std::nothrow) BasisThumbProviderFactory()) {
|
||||
hr = factory->QueryInterface(riid, ppv);
|
||||
factory->Release();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void DllAddRef() {
|
||||
#ifdef _DEBUG
|
||||
OutputDebugString(_T("DllAddRef"));
|
||||
#endif
|
||||
InterlockedIncrement(&dllRefs);
|
||||
}
|
||||
|
||||
void DllRelease() {
|
||||
#ifdef _DEBUG
|
||||
OutputDebugString(_T("DllRelease"));
|
||||
#endif
|
||||
InterlockedDecrement(&dllRefs);
|
||||
}
|
||||
|
||||
STDAPI DllCanUnloadNow() {
|
||||
#ifdef _DEBUG
|
||||
OutputDebugString(_T("DllCanUnloadNow"));
|
||||
#endif
|
||||
return (dllRefs == 0) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
// regsvr32 /s previewers.dll
|
||||
STDAPI DllRegisterServer() {
|
||||
HRESULT hr = E_FAIL;
|
||||
if (_tcslen(dllPath)) {
|
||||
BAIL_ON_FAIL(setRegKey(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\CLSID\\") THUMBNAIL_HANDLER_CLSID, NULL, THUMBNAIL_HANDLER_TITLE));
|
||||
BAIL_ON_FAIL(setRegKey(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\CLSID\\") THUMBNAIL_HANDLER_CLSID _T("\\InProcServer32"), NULL, dllPath));
|
||||
BAIL_ON_FAIL(setRegKey(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\CLSID\\") THUMBNAIL_HANDLER_CLSID _T("\\InProcServer32"), _T("ThreadingModel"), _T("Apartment")));
|
||||
BAIL_ON_FAIL(setRegKey(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\") FILE_EXTENSION _T("\\") SHELLEX_THUMBNAIL_CLSID, NULL, THUMBNAIL_HANDLER_CLSID));
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (SUCCEEDED(hr)) {
|
||||
OutputDebugString(_T("Previewer successfully registered"));
|
||||
}
|
||||
#endif
|
||||
return hr;
|
||||
}
|
||||
|
||||
// regsvr32 /s /u previewers.dll
|
||||
STDAPI DllUnregisterServer() {
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\CLSID\\") THUMBNAIL_HANDLER_CLSID));
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_LOCAL_MACHINE, _T("Software\\Classes\\") FILE_EXTENSION _T("\\") SHELLEX_THUMBNAIL_CLSID));
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (SUCCEEDED(hr)) {
|
||||
OutputDebugString(_T("Previewer successfully unregistered"));
|
||||
}
|
||||
#endif
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "previewers", "previewers.vcxproj", "{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Debug|x64.Build.0 = Debug|x64
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Release|Win32.Build.0 = Release|Win32
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Release|x64.ActiveCfg = Release|x64
|
||||
{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F3D4D2B1-20BF-44F2-B624-BE19C6911D4B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>previewers</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
|
||||
<IntDir>bin\$(PlatformShortName)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>bin\$(PlatformShortName)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
|
||||
<IntDir>bin\$(PlatformShortName)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>bin\$(PlatformShortName)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0601;_WINDOWS;_USRDLL;_ITERATOR_DEBUG_LEVEL=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<AdditionalIncludeDirectories>..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>previewers.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0601;_WINDOWS;_USRDLL;_ITERATOR_DEBUG_LEVEL=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<AdditionalIncludeDirectories>..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>previewers.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0601;_WINDOWS;_USRDLL;_ITERATOR_DEBUG_LEVEL=0;NDEBUG;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<AdditionalIncludeDirectories>..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>previewers.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0601;_WINDOWS;_USRDLL;_ITERATOR_DEBUG_LEVEL=0;NDEBUG;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<AdditionalIncludeDirectories>..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>previewers.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="basisthumbprovider.h" />
|
||||
<ClInclude Include="..\lib\basisu_transcoder.h" />
|
||||
<ClInclude Include="helpers.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="basisthumbprovider.cpp" />
|
||||
<ClCompile Include="helpers.cpp" />
|
||||
<ClCompile Include="previewers.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="inc">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="src">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="res">
|
||||
<UniqueIdentifier>{f4f72237-4818-48a4-9192-33d12efece22}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="basisthumbprovider.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="helpers.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\lib\basisu_transcoder.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="basisthumbprovider.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="previewers.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="helpers.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
@@ -0,0 +1,2 @@
|
||||
# Don't commit the generated files
|
||||
basisu_transcoder.*
|
||||
@@ -0,0 +1,34 @@
|
||||
# Single File Basis Universal Transcoder
|
||||
|
||||
The script `combine.py` creates an _amalgamated_ C++ source file that can be used with or without `basisu_transcoder.h`. This _isn't_ a header-only file but it does offer a similar level of simplicity when integrating into a project.
|
||||
|
||||
Create `basisu_transcoder.cpp` from the transcoder sources using:
|
||||
```
|
||||
cd basis_universal/contrib/single_file_transcoder
|
||||
|
||||
python3 combine.py -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
```
|
||||
Then add the resulting file to your project (see the [example files](examples)).
|
||||
|
||||
If certain features will _never__ be enabled, e.g. `BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY`, then `combine.py` can be told to exclude files with the `-x` option:
|
||||
```
|
||||
python3 combine.py -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
```
|
||||
Excluding the BC7 mode 6 support reduces the generated source by 1.2MB, which is the choice taken in `basisu_transcoder-in.cpp` and used in the examples, with `create_transcoder.sh` running the above script, creating the final `basisu_transcoder.cpp`.
|
||||
|
||||
The combiner script can also generate separate amalgamated header and source files, using the `-k` option to keep the specified inline directive, and `-p` to keep the `#pragma once` directives in the header:
|
||||
```
|
||||
python3 combine.py -r ../../transcoder -o basisu_transcoder.h -p ../../transcoder/basisu_transcoder.h
|
||||
|
||||
python3 combine.py -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -k basisu_transcoder.h -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
|
||||
```
|
||||
|
||||
Note: the amalgamation script was tested on Windows and Mac, requiring Python 3.8, with a fallback implementation as a shell script that will run on pretty much anything.
|
||||
|
||||
Why?
|
||||
----
|
||||
|
||||
Because all it now takes to support Basis Universal is the addition of a single file, two if using the header, with no configuration or further build steps (the out-of-the-box defaults tailor the included formats for various platforms).
|
||||
|
||||
The library is small, adding, for example, around 250kB to an Emscripten compiled WebAssembly project (with transcoding disabled for BC7 and ATC; disabling ASTC will remove a further 64kB, and `gzip` will approximately half the `wasm` file).
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Basis Universal single file library. Generated using:
|
||||
* \code
|
||||
* ./combine.py -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
/*
|
||||
* Transcoder build options for known platforms (iOS has ETC, ASTC and PVRTC;
|
||||
* Emscripten adds DXT to iOS's options; Android adds PVRTC2 to Emscripten's
|
||||
* options; other platforms build all except FXT1).
|
||||
*
|
||||
* See https://github.com/BinomialLLC/basis_universal#shrinking-the-transcoders-compiled-size
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#if TARGET_OS_IPHONE
|
||||
#define BASISD_SUPPORT_DXT1 0
|
||||
#define BASISD_SUPPORT_DXT5A 0
|
||||
#endif
|
||||
#if TARGET_OS_IPHONE || defined(__EMSCRIPTEN__) || defined(__ANDROID__)
|
||||
#define BASISD_SUPPORT_BC7 0
|
||||
#define BASISD_SUPPORT_ATC 0
|
||||
#ifndef __ANDROID__
|
||||
#define BASISD_SUPPORT_PVRTC2 0
|
||||
#endif
|
||||
#endif
|
||||
#define BASISD_SUPPORT_FXT1 0
|
||||
|
||||
/*
|
||||
* KTX2 support disabled.
|
||||
*/
|
||||
#define BASISD_SUPPORT_KTX2 0
|
||||
|
||||
#include "basisu_transcoder.cpp"
|
||||
|
||||
/**
|
||||
* Collection of unused functions and const variables to work around \c
|
||||
* -Wunused-function and \c -Wunused-const-variable warnings.
|
||||
*
|
||||
* \todo LTO does its thing so any unused are removed but is there a better way?
|
||||
*/
|
||||
void _basisu_translib_dummy() {
|
||||
// These first ones are not used at all
|
||||
BASISU_NOTE_UNUSED(&basisu::byteswap16);
|
||||
BASISU_NOTE_UNUSED(&basisu::byteswap32);
|
||||
BASISU_NOTE_UNUSED(basisu::BASISU_PATH_SEPERATOR_CHAR);
|
||||
BASISU_NOTE_UNUSED(basisu::cHuffmanTotalSortedCodelengthCodes);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL0_DELTA_LO);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL0_DELTA_HI);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL1_DELTA_LO);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL1_DELTA_HI);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL2_DELTA_LO);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL2_DELTA_HI);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL2_PREV_HI);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL_MIN_DELTA_B_RUNLEN);
|
||||
BASISU_NOTE_UNUSED(basist::COLOR5_PAL_DELTA_5_RUNLEN_VLC_BITS);
|
||||
BASISU_NOTE_UNUSED(basist::NO_ENDPOINT_PRED_INDEX);
|
||||
BASISU_NOTE_UNUSED(basist::MAX_SELECTOR_HISTORY_BUF_SIZE);
|
||||
#if BASISD_SUPPORT_ETC2_EAC_A8
|
||||
// Unused but only when building with EAC
|
||||
BASISU_NOTE_UNUSED(basist::g_eac_modifier_table);
|
||||
#endif
|
||||
#if BASISD_SUPPORT_PVRTC1 == 0
|
||||
// Unused only when not building with PVRTC
|
||||
BASISU_NOTE_UNUSED(basist::g_etc1_inten_tables16);
|
||||
BASISU_NOTE_UNUSED(basist::g_etc1_inten_tables48);
|
||||
BASISU_NOTE_UNUSED(basist::g_etc_5_to_8);
|
||||
BASISU_NOTE_UNUSED(basist::g_etc1_x_selector_unpack);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Tool to bundle multiple C/C++ source files, inlining any includes.
|
||||
#
|
||||
# Note: there are two types of exclusion options: the '-x' flag, which besides
|
||||
# excluding a file also adds an #error directive in place of the #include, and
|
||||
# the '-k' flag, which keeps the #include and doesn't inline the file. The
|
||||
# intended use cases are: '-x' for files that would normally be #if'd out, so
|
||||
# features that 100% won't be used in the amalgamated file, for which every
|
||||
# occurrence adds the error, and '-k' for headers that we wish to manually
|
||||
# include, such as a project's public API, for which occurrences after the first
|
||||
# are removed.
|
||||
#
|
||||
# Todo: the error handling could be better, which currently throws and halts
|
||||
# (which is functional just not very friendly).
|
||||
#
|
||||
# Author: Carl Woffenden, Numfum GmbH (this script is released under a CC0 license/Public Domain)
|
||||
|
||||
import argparse, re, sys
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, List, Optional, Pattern, Set, TextIO
|
||||
|
||||
# Set of file roots when searching (equivalent to -I paths for the compiler).
|
||||
roots: Set[Path] = set()
|
||||
|
||||
# Set of (canonical) file Path objects to exclude from inlining (and not only
|
||||
# exclude but to add a compiler error directive when they're encountered).
|
||||
excludes: Set[Path] = set()
|
||||
|
||||
# Set of (canonical) file Path objects to keep as include directives.
|
||||
keeps: Set[Path] = set()
|
||||
|
||||
# Whether to keep the #pragma once directives (unlikely, since this will result
|
||||
# in a warning, but the option is there).
|
||||
keep_pragma: bool = False
|
||||
|
||||
# Destination file object (or stdout if no output file was supplied).
|
||||
destn:TextIO = sys.stdout
|
||||
|
||||
# Set of file Path objects previously inlined (and to ignore if reencountering).
|
||||
found: Set[Path] = set()
|
||||
|
||||
# Compiled regex Patern to handle the following type of file includes:
|
||||
#
|
||||
# #include "file"
|
||||
# #include "file"
|
||||
# # include "file"
|
||||
# #include "file"
|
||||
# #include "file" // comment
|
||||
# #include "file" // comment with quote "
|
||||
#
|
||||
# And all combinations of, as well as ignoring the following:
|
||||
#
|
||||
# #include <file>
|
||||
# //#include "file"
|
||||
# /*#include "file"*/
|
||||
#
|
||||
# We don't try to catch errors since the compiler will do this (and the code is
|
||||
# expected to be valid before processing) and we don't care what follows the
|
||||
# file (whether it's a valid comment or not, since anything after the quoted
|
||||
# string is ignored)
|
||||
#
|
||||
include_regex: Pattern = re.compile(r'^\s*#\s*include\s*"(.+?)"')
|
||||
|
||||
# Simple tests to prove include_regex's cases.
|
||||
#
|
||||
def test_match_include() -> bool:
|
||||
if (include_regex.match('#include "file"') and
|
||||
include_regex.match(' #include "file"') and
|
||||
include_regex.match('# include "file"') and
|
||||
include_regex.match('#include "file"') and
|
||||
include_regex.match('#include "file" // comment')):
|
||||
if (not include_regex.match('#include <file>') and
|
||||
not include_regex.match('//#include "file"') and
|
||||
not include_regex.match('/*#include "file"*/')):
|
||||
found = include_regex.match('#include "file" // "')
|
||||
if (found and found.group(1) == 'file'):
|
||||
print('#include match valid')
|
||||
return True
|
||||
return False
|
||||
|
||||
# Compiled regex Patern to handle "#pragma once" in various formats:
|
||||
#
|
||||
# #pragma once
|
||||
# #pragma once
|
||||
# # pragma once
|
||||
# #pragma once
|
||||
# #pragma once // comment
|
||||
#
|
||||
# Ignoring commented versions, same as include_regex.
|
||||
#
|
||||
pragma_regex: Pattern = re.compile(r'^\s*#\s*pragma\s*once\s*')
|
||||
|
||||
# Simple tests to prove pragma_regex's cases.
|
||||
#
|
||||
def text_match_pragma() -> bool:
|
||||
if (pragma_regex.match('#pragma once') and
|
||||
pragma_regex.match(' #pragma once') and
|
||||
pragma_regex.match('# pragma once') and
|
||||
pragma_regex.match('#pragma once') and
|
||||
pragma_regex.match('#pragma once // comment')):
|
||||
if (not pragma_regex.match('//#pragma once') and
|
||||
not pragma_regex.match('/*#pragma once*/')):
|
||||
print('#pragma once match valid')
|
||||
return True
|
||||
return False
|
||||
|
||||
# Finds 'file'. First the list of 'root' paths are searched, followed by the
|
||||
# the currently processing file's 'parent' path, returning a valid Path in
|
||||
# canonical form. If no match is found None is returned.
|
||||
#
|
||||
def resolve_include(file: str, parent: Optional[Path] = None) -> Optional[Path]:
|
||||
for root in roots:
|
||||
found = root.joinpath(file).resolve()
|
||||
if (found.is_file()):
|
||||
return found
|
||||
if (parent):
|
||||
found = parent.joinpath(file).resolve();
|
||||
else:
|
||||
found = Path(file)
|
||||
if (found.is_file()):
|
||||
return found
|
||||
return None
|
||||
|
||||
# Helper to resolve lists of files. 'file_list' is passed in from the arguments
|
||||
# and each entry resolved to its canonical path (like any include entry, either
|
||||
# from the list of root paths or the owning file's 'parent', which in this case
|
||||
# is case is the input file). The results are stored in 'resolved'.
|
||||
#
|
||||
def resolve_excluded_files(file_list: Optional[List[str]], resolved: Set[Path], parent: Optional[Path] = None) -> None:
|
||||
if (file_list):
|
||||
for filename in file_list:
|
||||
found = resolve_include(filename, parent)
|
||||
if (found):
|
||||
resolved.add(found)
|
||||
else:
|
||||
error_line(f'Warning: excluded file not found: {filename}')
|
||||
|
||||
# Writes 'line' to the open 'destn' (or stdout).
|
||||
#
|
||||
def write_line(line: str) -> None:
|
||||
print(line, file=destn)
|
||||
|
||||
# Logs 'line' to stderr. This is also used for general notifications that we
|
||||
# don't want to go to stdout (so the source can be piped).
|
||||
#
|
||||
def error_line(line: Any) -> None:
|
||||
print(line, file=sys.stderr)
|
||||
|
||||
# Inline the contents of 'file' (with any of its includes also inlined, etc.).
|
||||
#
|
||||
# Note: text encoding errors are ignored and replaced with ? when reading the
|
||||
# input files. This isn't ideal, but it's more than likely in the comments than
|
||||
# code and a) the text editor has probably also failed to read the same content,
|
||||
# and b) the compiler probably did too.
|
||||
#
|
||||
def add_file(file: Path, file_name: str = None) -> None:
|
||||
if (file.is_file()):
|
||||
if (not file_name):
|
||||
file_name = file.name
|
||||
error_line(f'Processing: {file_name}')
|
||||
with file.open('r', errors='replace') as opened:
|
||||
for line in opened:
|
||||
line = line.rstrip('\n')
|
||||
match_include = include_regex.match(line);
|
||||
if (match_include):
|
||||
# We have a quoted include directive so grab the file
|
||||
inc_name = match_include.group(1)
|
||||
resolved = resolve_include(inc_name, file.parent)
|
||||
if (resolved):
|
||||
if (resolved in excludes):
|
||||
# The file was excluded so error if the compiler uses it
|
||||
write_line(f'#error Using excluded file: {inc_name}')
|
||||
error_line(f'Excluding: {inc_name}')
|
||||
else:
|
||||
if (resolved not in found):
|
||||
# The file was not previously encountered
|
||||
found.add(resolved)
|
||||
if (resolved in keeps):
|
||||
# But the include was flagged to keep as included
|
||||
write_line(f'/**** *NOT* inlining {inc_name} ****/')
|
||||
write_line(line)
|
||||
error_line(f'Not inlining: {inc_name}')
|
||||
else:
|
||||
# The file was neither excluded nor seen before so inline it
|
||||
write_line(f'/**** start inlining {inc_name} ****/')
|
||||
add_file(resolved, inc_name)
|
||||
write_line(f'/**** ended inlining {inc_name} ****/')
|
||||
else:
|
||||
write_line(f'/**** skipping file: {inc_name} ****/')
|
||||
else:
|
||||
# The include file didn't resolve to a file
|
||||
write_line(f'#error Unable to find: {inc_name}')
|
||||
error_line(f'Error: Unable to find: {inc_name}')
|
||||
else:
|
||||
# Skip any 'pragma once' directives, otherwise write the source line
|
||||
if (keep_pragma or not pragma_regex.match(line)):
|
||||
write_line(line)
|
||||
else:
|
||||
error_line(f'Error: Invalid file: {file}')
|
||||
|
||||
# Start here
|
||||
parser = argparse.ArgumentParser(description='Amalgamate Tool', epilog=f'example: {sys.argv[0]} -r ../my/path -r ../other/path -o out.c in.c')
|
||||
parser.add_argument('-r', '--root', action='append', type=Path, help='file root search path')
|
||||
parser.add_argument('-x', '--exclude', action='append', help='file to completely exclude from inlining')
|
||||
parser.add_argument('-k', '--keep', action='append', help='file to exclude from inlining but keep the include directive')
|
||||
parser.add_argument('-p', '--pragma', action='store_true', default=False, help='keep any "#pragma once" directives (removed by default)')
|
||||
parser.add_argument('-o', '--output', type=argparse.FileType('w'), help='output file (otherwise stdout)')
|
||||
parser.add_argument('input', type=Path, help='input file')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Fail early on an invalid input (and store it so we don't recurse)
|
||||
args.input = args.input.resolve(strict=True)
|
||||
found.add(args.input)
|
||||
|
||||
# Resolve all of the root paths upfront (we'll halt here on invalid roots)
|
||||
if (args.root):
|
||||
for path in args.root:
|
||||
roots.add(path.resolve(strict=True))
|
||||
|
||||
# The remaining params: so resolve the excluded files and #pragma once directive
|
||||
resolve_excluded_files(args.exclude, excludes, args.input.parent)
|
||||
resolve_excluded_files(args.keep, keeps, args.input.parent)
|
||||
keep_pragma = args.pragma;
|
||||
|
||||
# Then recursively process the input file
|
||||
try:
|
||||
if (args.output):
|
||||
destn = args.output
|
||||
add_file(args.input)
|
||||
finally:
|
||||
if (not destn):
|
||||
destn.close()
|
||||
@@ -0,0 +1,166 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# Tool to bundle multiple C/C++ source files, inlining any includes.
|
||||
#
|
||||
# Note: this POSIX-compliant script is many times slower than the original bash
|
||||
# implementation (due to the grep calls) but it runs and works everywhere.
|
||||
#
|
||||
# TODO: ROOTS, FOUND, etc., as arrays (since they fail on paths with spaces)
|
||||
# TODO: revert to Bash-only regex (the grep ones being too slow)
|
||||
#
|
||||
# Script released under a CC0 license.
|
||||
|
||||
# Common file roots
|
||||
ROOTS="."
|
||||
|
||||
# -x option excluded includes
|
||||
XINCS=""
|
||||
|
||||
# -k option includes to keep as include directives
|
||||
KINCS=""
|
||||
|
||||
# Files previously visited
|
||||
FOUND=""
|
||||
|
||||
# Optional destination file (empty string to write to stdout)
|
||||
DESTN=""
|
||||
|
||||
# Whether the "#pragma once" directives should be written to the output
|
||||
PONCE=0
|
||||
|
||||
# Prints the script usage then exits
|
||||
usage() {
|
||||
echo "Usage: $0 [-r <path>] [-x <header>] [-k <header>] [-o <outfile>] infile"
|
||||
echo " -r file root search path"
|
||||
echo " -x file to completely exclude from inlining"
|
||||
echo " -k file to exclude from inlining but keep the include directive"
|
||||
echo " -p keep any '#pragma once' directives (removed by default)"
|
||||
echo " -o output file (otherwise stdout)"
|
||||
echo "Example: $0 -r ../my/path - r ../other/path -o out.c in.c"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Tests that the grep implementation works as expected (older OSX grep fails)
|
||||
test_grep() {
|
||||
if ! echo '#include "foo"' | grep -Eq '^\s*#\s*include\s*".+"'; then
|
||||
echo "Aborting: the grep implementation fails to parse include lines"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Tests if list $1 has item $2 (returning zero on a match)
|
||||
list_has_item() {
|
||||
if echo "$1" | grep -Eq "(^|\s*)$2(\$|\s*)"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Adds a new line with the supplied arguments to $DESTN (or stdout)
|
||||
write_line() {
|
||||
if [ -n "$DESTN" ]; then
|
||||
printf '%s\n' "$@" >> "$DESTN"
|
||||
else
|
||||
printf '%s\n' "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Adds the contents of $1 with any of its includes inlined
|
||||
add_file() {
|
||||
# Match the path
|
||||
local file=
|
||||
for root in $ROOTS; do
|
||||
if [ -f "$root/$1" ]; then
|
||||
file="$root/$1"
|
||||
fi
|
||||
done
|
||||
if [ -n "$file" ]; then
|
||||
if [ -n "$DESTN" ]; then
|
||||
# Log but only if not writing to stdout
|
||||
echo "Processing: $file"
|
||||
fi
|
||||
# Read the file
|
||||
local line=
|
||||
while IFS= read -r line; do
|
||||
if echo "$line" | grep -Eq '^\s*#\s*include\s*".+"'; then
|
||||
# We have an include directive so strip the (first) file
|
||||
local inc=$(echo "$line" | grep -Eo '".*"' | grep -Eo '\w*(\.?\w+)+' | head -1)
|
||||
if list_has_item "$XINCS" "$inc"; then
|
||||
# The file was excluded so error if the source attempts to use it
|
||||
write_line "#error Using excluded file: $inc"
|
||||
else
|
||||
if ! list_has_item "$FOUND" "$inc"; then
|
||||
# The file was not previously encountered
|
||||
FOUND="$FOUND $inc"
|
||||
if list_has_item "$KINCS" "$inc"; then
|
||||
# But the include was flagged to keep as included
|
||||
write_line "/**** *NOT* inlining $inc ****/"
|
||||
write_line "$line"
|
||||
else
|
||||
# The file was neither excluded nor seen before so inline it
|
||||
write_line "/**** start inlining $inc ****/"
|
||||
add_file "$inc"
|
||||
write_line "/**** ended inlining $inc ****/"
|
||||
fi
|
||||
else
|
||||
write_line "/**** skipping file: $inc ****/"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Skip any 'pragma once' directives, otherwise write the source line
|
||||
local write=$PONCE
|
||||
if [ $write -eq 0 ]; then
|
||||
if echo "$line" | grep -Eqv '^\s*#\s*pragma\s*once\s*'; then
|
||||
write=1
|
||||
fi
|
||||
fi
|
||||
if [ $write -ne 0 ]; then
|
||||
write_line "$line"
|
||||
fi
|
||||
fi
|
||||
done < "$file"
|
||||
else
|
||||
write_line "#error Unable to find \"$1\""
|
||||
fi
|
||||
}
|
||||
|
||||
while getopts ":r:x:k:po:" opts; do
|
||||
case $opts in
|
||||
r)
|
||||
ROOTS="$ROOTS $OPTARG"
|
||||
;;
|
||||
x)
|
||||
XINCS="$XINCS $OPTARG"
|
||||
;;
|
||||
k)
|
||||
KINCS="$KINCS $OPTARG"
|
||||
;;
|
||||
p)
|
||||
PONCE=1
|
||||
;;
|
||||
o)
|
||||
DESTN="$OPTARG"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
if [ -f "$1" ]; then
|
||||
if [ -n "$DESTN" ]; then
|
||||
printf "" > "$DESTN"
|
||||
fi
|
||||
test_grep
|
||||
add_file $1
|
||||
else
|
||||
echo "Input file not found: \"$1\""
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
usage
|
||||
fi
|
||||
exit 0
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Temporary compiled binary
|
||||
OUT_FILE="tempbin"
|
||||
|
||||
echo "Amalgamating files... this can take a while"
|
||||
# Use the faster Python script if we have 3.8 or higher
|
||||
if python3 -c 'import sys; assert sys.version_info >= (3,8)' 2>/dev/null; then
|
||||
./combine.py -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
else
|
||||
./combine.sh -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
|
||||
fi
|
||||
# Did combining work?
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Combine script: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
echo "Combine script: PASSED"
|
||||
|
||||
# Compile the generated output
|
||||
which cc > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "(Skipping compile test)"
|
||||
else
|
||||
cc -lm -std=c++11 -lstdc++ -Wall -Wextra -Werror -Os -g0 -fno-exceptions -fno-rtti -o $OUT_FILE examples/simple.cpp
|
||||
# Did compilation work?
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Compiling simple.cpp: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
# Run then delete the compiled output
|
||||
./$OUT_FILE
|
||||
retVal=$?
|
||||
rm -f $OUT_FILE
|
||||
# Did the test work?
|
||||
if [ $retVal -ne 0 ]; then
|
||||
echo "Running simple.cpp: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
echo "Running simple.cpp: PASSED"
|
||||
fi
|
||||
@@ -0,0 +1,7 @@
|
||||
# Single File Basis Universal Examples
|
||||
|
||||
The examples `#include` the generated `basisu_transcoder.cpp` directly but work equally as well when including `basisu_transcoder.h` and compiling the amalgamated source separately.
|
||||
|
||||
`emscripten.cpp` is a bare-bones [Emscripten](https://github.com/emscripten-core/emscripten) compiled WebGL demo picking the best transcoder format for the sample texture (see the [original PNG image](testcard.png)).
|
||||
|
||||
The example files in this directory are released under a [Creative Commons Zero license](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
@@ -0,0 +1,568 @@
|
||||
/**
|
||||
* \file emscripten.cpp
|
||||
* Emscripten example of using the single-file \c basisu_transcoder.cpp. Draws
|
||||
* a rotating textured quad with data from the in-line compressed textures.
|
||||
* \n
|
||||
* Compile using:
|
||||
* \code
|
||||
* export "CC_FLAGS=-std=c++11 -Wall -Wextra -Werror -Os -g0 -flto --llvm-lto 3 -fno-exceptions -fno-rtti -lGL -DNDEBUG=1"
|
||||
* export "EM_FLAGS=-s ENVIRONMENT=web -s WASM=1 --shell-file shell.html --closure 1"
|
||||
* emcc $CC_FLAGS $EM_FLAGS -o out.html emscripten.cpp
|
||||
* \endcode
|
||||
* Alternatively include \c basisu_transcoder.h and compile \c
|
||||
* basisu_transcoder.cpp separately (the resulting binary is exactly the same
|
||||
* size):
|
||||
* \code
|
||||
* emcc $CC_FLAGS $EM_FLAGS -o out.html ../basisu_transcoder.cpp emscripten.cpp
|
||||
* \encode
|
||||
* To determine the WebAssembly size without the transcoder comment the \c
|
||||
* basisu_transcoder.cpp include (which stubs the texture creation).
|
||||
* \n
|
||||
* Example code released under a CC0 license.
|
||||
*/
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include "../basisu_transcoder.cpp"
|
||||
|
||||
//********************************* Test Data ********************************/
|
||||
|
||||
/**
|
||||
* Basis Universal compressed 256x256 RGB texture source (with mipmaps).
|
||||
* \n
|
||||
* See \c testcard.png for the original. Generate using:
|
||||
* \code
|
||||
* basisu -comp_level 5 -linear -global_sel_pal -y_flip -mipmap
|
||||
* \endcode
|
||||
*/
|
||||
static uint8_t const srcRgb[] = {
|
||||
#include "testcard.basis.inc"
|
||||
};
|
||||
|
||||
/**
|
||||
* Basis Universal compressed 256x256 RGBA texture source (with mipmaps).
|
||||
* \n
|
||||
* See \c testcard-rgba.png for the original. Generate using:
|
||||
* \code
|
||||
* basisu -comp_level 5 -linear -global_sel_pal -y_flip -mipmap
|
||||
* \endcode
|
||||
*/
|
||||
static uint8_t const srcRgba[] = {
|
||||
#include "testcard-rgba.basis.inc"
|
||||
};
|
||||
|
||||
//*************************** Program and Shaders ***************************/
|
||||
|
||||
/**
|
||||
* Program object ID.
|
||||
*/
|
||||
static GLuint progId = 0;
|
||||
|
||||
/**
|
||||
* Vertex shader ID.
|
||||
*/
|
||||
static GLuint vertId = 0;
|
||||
|
||||
/**
|
||||
* Fragment shader ID.
|
||||
*/
|
||||
static GLuint fragId = 0;
|
||||
|
||||
//********************************* Uniforms *********************************/
|
||||
|
||||
/**
|
||||
* Quad rotation angle ID.
|
||||
*/
|
||||
static GLint uRotId = -1;
|
||||
|
||||
/**
|
||||
* Texture ID.
|
||||
*/
|
||||
static GLint uTx0Id = -1;
|
||||
|
||||
//******************************* Shader Source ******************************/
|
||||
|
||||
/**
|
||||
* Vertex shader to draw texture mapped polys with an applied rotation.
|
||||
*/
|
||||
static GLchar const vertShader2D[] =
|
||||
#if GL_ES_VERSION_2_0
|
||||
"#version 100\n"
|
||||
"precision mediump float;\n"
|
||||
#else
|
||||
"#version 120\n"
|
||||
#endif
|
||||
"uniform float uRot;" // rotation
|
||||
"attribute vec2 aPos;" // vertex position coords
|
||||
"attribute vec2 aUV0;" // vertex texture UV0
|
||||
"varying vec2 vUV0;" // (passed to fragment shader)
|
||||
"void main() {"
|
||||
" float cosA = cos(radians(uRot));"
|
||||
" float sinA = sin(radians(uRot));"
|
||||
" mat3 rot = mat3(cosA, -sinA, 0.0,"
|
||||
" sinA, cosA, 0.0,"
|
||||
" 0.0, 0.0, 1.0);"
|
||||
" gl_Position = vec4(rot * vec3(aPos, 1.0), 1.0);"
|
||||
" vUV0 = aUV0;"
|
||||
"}";
|
||||
|
||||
/**
|
||||
* Fragment shader for the above polys.
|
||||
*/
|
||||
static GLchar const fragShader2D[] =
|
||||
#if GL_ES_VERSION_2_0
|
||||
"#version 100\n"
|
||||
"precision mediump float;\n"
|
||||
#else
|
||||
"#version 120\n"
|
||||
#endif
|
||||
"uniform sampler2D uTx0;"
|
||||
"varying vec2 vUV0;" // (passed from fragment shader)
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(uTx0, vUV0);"
|
||||
"}";
|
||||
|
||||
/**
|
||||
* Helper to compile a shader.
|
||||
*
|
||||
* \param type shader type
|
||||
* \param text shader source
|
||||
* \return the shader ID (or zero if compilation failed)
|
||||
*/
|
||||
static GLuint compileShader(GLenum const type, const GLchar* text) {
|
||||
GLuint shader = glCreateShader(type);
|
||||
if (shader) {
|
||||
glShaderSource (shader, 1, &text, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint compiled;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||
if (compiled) {
|
||||
return shader;
|
||||
} else {
|
||||
GLint logLen;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);
|
||||
if (logLen > 1) {
|
||||
GLchar* logStr = static_cast<GLchar*>(malloc(logLen));
|
||||
glGetShaderInfoLog(shader, logLen, NULL, logStr);
|
||||
#ifndef NDEBUG
|
||||
printf("Shader compilation error: %s\n", logStr);
|
||||
#endif
|
||||
free(logStr);
|
||||
}
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//********************************** Helpers *********************************/
|
||||
|
||||
/**
|
||||
* Vertex position index.
|
||||
*/
|
||||
#define GL_VERT_POSXY_ID 0
|
||||
|
||||
/**
|
||||
* Vertex UV0 index.
|
||||
*/
|
||||
#define GL_VERT_TXUV0_ID 1
|
||||
|
||||
/**
|
||||
* \c GL vec2 storage type.
|
||||
*/
|
||||
struct vec2 {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Combined 2D vertex and 2D texture coordinates.
|
||||
*/
|
||||
struct posTex2d {
|
||||
struct vec2 pos;
|
||||
struct vec2 uv0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shortcut for \c emscripten_webgl_enable_extension().
|
||||
*/
|
||||
#ifndef GL_HAS_EXT
|
||||
#define GL_HAS_EXT(ctx, ext) emscripten_webgl_enable_extension(ctx, ext)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Possibly missing GL enums.
|
||||
*
|
||||
* Note: GL_COMPRESSED_RGB_ETC1_WEBGL is the same as GL_ETC1_RGB8_OES
|
||||
*/
|
||||
#ifndef GL_ETC1_RGB8_OES
|
||||
#define GL_ETC1_RGB8_OES 0x8D64
|
||||
#endif
|
||||
#ifndef GL_COMPRESSED_RGB8_ETC2
|
||||
#define GL_COMPRESSED_RGB8_ETC2 0x9274
|
||||
#endif
|
||||
#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
|
||||
#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
||||
#endif
|
||||
#ifndef COMPRESSED_RGBA_ASTC_4x4_KHR
|
||||
#define COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
|
||||
#endif
|
||||
|
||||
//***************************** Basis Universal ******************************/
|
||||
|
||||
/*
|
||||
* All of the BasisU code is within this block to enable building with or
|
||||
* without the library. Not including the transcoder will build a dummy
|
||||
* implementation to (roughly) determine the size.
|
||||
*/
|
||||
#ifdef BASISD_LIB_VERSION
|
||||
|
||||
using namespace basist;
|
||||
|
||||
/**
|
||||
* Shared codebook instance.
|
||||
*/
|
||||
static etc1_global_selector_codebook* globalCodebook = NULL;
|
||||
|
||||
/**
|
||||
* Returns a supported compressed texture format for a given context.
|
||||
*
|
||||
* \param[in] ctx WebGL context
|
||||
* \param[in] alpha \c true if the texture has an alpha channel
|
||||
* \return corresponding Basis format
|
||||
*/
|
||||
static transcoder_texture_format supports(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE const ctx, bool const alpha) {
|
||||
#if BASISD_SUPPORT_PVRTC1 || !defined(BASISD_SUPPORT_PVRTC1)
|
||||
/*
|
||||
* Test for both prefixed and non-prefixed versions. This should grab iOS
|
||||
* and other ImgTec GPUs first as a preference.
|
||||
*
|
||||
* TODO: do older iOS expose ASTC to the browser and does it transcode to RGBA?
|
||||
*/
|
||||
static bool const pvr = GL_HAS_EXT(ctx, "WEBKIT_WEBGL_compressed_texture_pvrtc")
|
||||
|| GL_HAS_EXT(ctx, "WEBGL_compressed_texture_pvrtc");
|
||||
if (pvr) {
|
||||
return (alpha)
|
||||
? transcoder_texture_format::cTFPVRTC1_4_RGBA
|
||||
: transcoder_texture_format::cTFPVRTC1_4_RGB;
|
||||
}
|
||||
#endif
|
||||
#if BASISD_SUPPORT_ASTC || !defined(BASISD_SUPPORT_ASTC)
|
||||
/*
|
||||
* Then Android, ChromeOS and others with ASTC (newer iOS devices should
|
||||
* make the list but don't appear to be exposed from WebGL).
|
||||
*/
|
||||
static bool const astc = GL_HAS_EXT(ctx, "WEBGL_compressed_texture_astc");
|
||||
if (astc) {
|
||||
return transcoder_texture_format::cTFASTC_4x4_RGBA;
|
||||
}
|
||||
#endif
|
||||
#if BASISD_SUPPORT_DXT1 || !defined(BASISD_SUPPORT_DXT1)
|
||||
/*
|
||||
* We choose DXT next, since a worry is the browser will claim ETC support
|
||||
* then transcode (transcoding slower and with more artefacts). This gives
|
||||
* us desktop and various (usually Intel) Android devices.
|
||||
*/
|
||||
static bool const dxt = GL_HAS_EXT(ctx, "WEBGL_compressed_texture_s3tc")
|
||||
|| GL_HAS_EXT(ctx, "WEBKIT_WEBGL_compressed_texture_s3tc");
|
||||
if (dxt) {
|
||||
return (alpha)
|
||||
? transcoder_texture_format::cTFBC3_RGBA
|
||||
: transcoder_texture_format::cTFBC1_RGB;
|
||||
}
|
||||
#endif
|
||||
#if BASISD_SUPPORT_ETC2_EAC_A8 || !defined(BASISD_SUPPORT_ETC2_EAC_A8)
|
||||
/*
|
||||
* Then ETC2 (which may be incorrect).
|
||||
*/
|
||||
static bool const etc2 = GL_HAS_EXT(ctx, "WEBGL_compressed_texture_etc");
|
||||
if (etc2) {
|
||||
return (alpha)
|
||||
? transcoder_texture_format::cTFETC2_RGBA
|
||||
: transcoder_texture_format::cTFETC1_RGB;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Finally ETC1, falling back on RGBA.
|
||||
*
|
||||
* TODO: we might just prefer to transcode to dithered 565 once available
|
||||
*/
|
||||
static bool const etc1 = GL_HAS_EXT(ctx, "WEBGL_compressed_texture_etc1");
|
||||
if (etc1 && !alpha) {
|
||||
return transcoder_texture_format::cTFETC1_RGB;
|
||||
}
|
||||
/*
|
||||
* We choose 8888 over 4444 and 565 (in the hope that is is never chosen).
|
||||
*/
|
||||
return transcoder_texture_format::cTFRGBA32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the equivalent GL type given a BasisU type.
|
||||
*
|
||||
* \note This relies on \c #supports() returning the supported formats, and so
|
||||
* only converts to the GL equivalents (without further testing for support).
|
||||
*
|
||||
* \param[in] type BasisU transcode target
|
||||
* \return equivalent GL type
|
||||
*/
|
||||
static GLenum toGlType(transcoder_texture_format const type) {
|
||||
switch (type) {
|
||||
case transcoder_texture_format::cTFETC1_RGB:
|
||||
return GL_ETC1_RGB8_OES;
|
||||
case transcoder_texture_format::cTFETC2_RGBA:
|
||||
return GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
case transcoder_texture_format::cTFBC1_RGB:
|
||||
return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||
case transcoder_texture_format::cTFBC3_RGBA:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
case transcoder_texture_format::cTFPVRTC1_4_RGB:
|
||||
return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
|
||||
case transcoder_texture_format::cTFPVRTC1_4_RGBA:
|
||||
return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
case transcoder_texture_format::cTFASTC_4x4_RGBA:
|
||||
return GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
||||
case transcoder_texture_format::cTFRGBA32:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case transcoder_texture_format::cTFRGB565:
|
||||
return GL_UNSIGNED_SHORT_5_6_5;
|
||||
default:
|
||||
return GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads the texture.
|
||||
*
|
||||
* \param[in] ctx ctx WebGL context
|
||||
* \param[in] name texture \e name
|
||||
* \param[in] data \c .basis file content
|
||||
* \param[in] size number of bytes in \a data
|
||||
* \return \c true if the texture was decoded and created
|
||||
*
|
||||
* \todo reuse the decode buffer (the first mips level should be able to contain the rest)
|
||||
*/
|
||||
bool upload(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE const ctx, GLuint const name, const uint8_t* const data, size_t const size) {
|
||||
basisu_transcoder_init();
|
||||
if (!globalCodebook) {
|
||||
globalCodebook = new etc1_global_selector_codebook(g_global_selector_cb_size, g_global_selector_cb);
|
||||
}
|
||||
basisu_transcoder transcoder(globalCodebook);
|
||||
bool success = false;
|
||||
if (transcoder.validate_header(data, size)) {
|
||||
glBindTexture(GL_TEXTURE_2D, name);
|
||||
basisu_file_info fileInfo;
|
||||
if (transcoder.get_file_info(data, size, fileInfo)) {
|
||||
transcoder_texture_format type = supports(ctx, fileInfo.m_has_alpha_slices);
|
||||
basisu_image_info info;
|
||||
if (transcoder.get_image_info(data, size, info, 0)) {
|
||||
printf("Transcoding to type: %s (w: %d, h: %d, mips: %d)\n",
|
||||
basis_get_format_name(type), info.m_width, info.m_height,
|
||||
info.m_total_levels);
|
||||
if (transcoder.start_transcoding(data, size)) {
|
||||
uint32_t descW, descH, blocks;
|
||||
for (uint32_t level = 0; level < info.m_total_levels; level++) {
|
||||
// reset per level
|
||||
success = false;
|
||||
if (transcoder.get_image_level_desc(data, size, 0, level, descW, descH, blocks)) {
|
||||
uint32_t decSize;
|
||||
if (type == transcoder_texture_format::cTFPVRTC1_4_RGB ||
|
||||
type == transcoder_texture_format::cTFPVRTC1_4_RGBA)
|
||||
{
|
||||
decSize = (std::max(8U, (descW + 3) & ~3) *
|
||||
std::max(8U, (descH + 3) & ~3) * 4 + 7) / 8;
|
||||
} else {
|
||||
decSize = basis_get_bytes_per_block_or_pixel(type);
|
||||
if (basis_transcoder_format_is_uncompressed(type)) {
|
||||
decSize *= descW * descH;
|
||||
} else {
|
||||
decSize *= blocks;
|
||||
}
|
||||
}
|
||||
if (void* decBuf = malloc(decSize)) {
|
||||
if (basis_transcoder_format_is_uncompressed(type)) {
|
||||
// note that blocks becomes total number of pixels for RGB/RGBA
|
||||
blocks = descW * descH;
|
||||
}
|
||||
if (transcoder.transcode_image_level(data, size, 0, level, decBuf, blocks, type)) {
|
||||
if (basis_transcoder_format_is_uncompressed(type)) {
|
||||
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
|
||||
descW, descH, 0, GL_RGBA, toGlType(type), decBuf);
|
||||
} else {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, level,
|
||||
toGlType(type), descW, descH, 0, decSize, decBuf);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
free(decBuf);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#else
|
||||
// dummy implementation
|
||||
bool upload(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE /*ctx*/, GLuint /*name*/, const uint8_t* data, size_t size) {
|
||||
return (data[0] | data[size - 1]) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//****************************************************************************/
|
||||
|
||||
/**
|
||||
* Current quad rotation angle (in degrees, updated per frame).
|
||||
*/
|
||||
static float rotDeg = 0.0f;
|
||||
|
||||
/**
|
||||
* Decoded textures (0 = opaque, 1 = transparent).
|
||||
*/
|
||||
static GLuint txName[2] = {};
|
||||
|
||||
/**
|
||||
* Emscripten (single) GL context.
|
||||
*/
|
||||
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glCtx = 0;
|
||||
|
||||
/**
|
||||
* Emscripten resize handler.
|
||||
*/
|
||||
static EM_BOOL resize(int /*type*/, const EmscriptenUiEvent* /*e*/, void* /*data*/) {
|
||||
double surfaceW;
|
||||
double surfaceH;
|
||||
if (emscripten_get_element_css_size ("#canvas", &surfaceW, &surfaceH) == EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
emscripten_set_canvas_element_size("#canvas", surfaceW, surfaceH);
|
||||
if (glCtx) {
|
||||
glViewport(0, 0, (int) surfaceW, (int) surfaceH);
|
||||
}
|
||||
}
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boilerplate to create a WebGL context.
|
||||
*/
|
||||
static EM_BOOL initContext() {
|
||||
// Default attributes
|
||||
EmscriptenWebGLContextAttributes attr;
|
||||
emscripten_webgl_init_context_attributes(&attr);
|
||||
if ((glCtx = emscripten_webgl_create_context("#canvas", &attr))) {
|
||||
// Bind the context and fire a resize to get the initial size
|
||||
emscripten_webgl_make_context_current(glCtx);
|
||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, resize);
|
||||
resize(0, NULL, NULL);
|
||||
return EM_TRUE;
|
||||
}
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once per frame (clears the screen and draws the rotating quad).
|
||||
*/
|
||||
static void tick() {
|
||||
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
if (uRotId >= 0) {
|
||||
glUniform1f(uRotId, rotDeg);
|
||||
rotDeg += 0.1f;
|
||||
if (rotDeg >= 360.0f) {
|
||||
rotDeg -= 360.0f;
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, txName[(lround(rotDeg / 45) & 1) != 0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the GL context, shaders and quad data, decompresses the .basis files
|
||||
* and 'uploads' the resulting textures.
|
||||
*/
|
||||
int main() {
|
||||
if (initContext()) {
|
||||
// Compile shaders and set the initial GL state
|
||||
if ((progId = glCreateProgram())) {
|
||||
vertId = compileShader(GL_VERTEX_SHADER, vertShader2D);
|
||||
fragId = compileShader(GL_FRAGMENT_SHADER, fragShader2D);
|
||||
|
||||
glBindAttribLocation(progId, GL_VERT_POSXY_ID, "aPos");
|
||||
glBindAttribLocation(progId, GL_VERT_TXUV0_ID, "aUV0");
|
||||
|
||||
glAttachShader(progId, vertId);
|
||||
glAttachShader(progId, fragId);
|
||||
glLinkProgram (progId);
|
||||
glUseProgram (progId);
|
||||
uRotId = glGetUniformLocation(progId, "uRot");
|
||||
uTx0Id = glGetUniformLocation(progId, "uTx0");
|
||||
if (uTx0Id >= 0) {
|
||||
glUniform1i(uTx0Id, 0);
|
||||
}
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
GLuint vertsBuf = 0;
|
||||
GLuint indexBuf = 0;
|
||||
// Create the textured quad (vert positions then UVs)
|
||||
struct posTex2d verts2d[] = {
|
||||
{{-0.85f, -0.85f}, {0.0f, 0.0f}}, // BL
|
||||
{{ 0.85f, -0.85f}, {1.0f, 0.0f}}, // BR
|
||||
{{-0.85f, 0.85f}, {0.0f, 1.0f}}, // TL
|
||||
{{ 0.85f, 0.85f}, {1.0f, 1.0f}}, // TR
|
||||
};
|
||||
uint16_t index2d[] = {
|
||||
0, 1, 2,
|
||||
2, 1, 3,
|
||||
};
|
||||
glGenBuffers(1, &vertsBuf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertsBuf);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(verts2d), verts2d, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(GL_VERT_POSXY_ID, 2,
|
||||
GL_FLOAT, GL_FALSE, sizeof(struct posTex2d), 0);
|
||||
glVertexAttribPointer(GL_VERT_TXUV0_ID, 2,
|
||||
GL_FLOAT, GL_FALSE, sizeof(struct posTex2d),
|
||||
(void*) offsetof(struct posTex2d, uv0));
|
||||
glGenBuffers(1, &indexBuf);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
sizeof(index2d), index2d, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(GL_VERT_POSXY_ID);
|
||||
glEnableVertexAttribArray(GL_VERT_TXUV0_ID);
|
||||
|
||||
glGenTextures(2, txName);
|
||||
if (upload(glCtx, txName[0], srcRgb, sizeof srcRgb) &&
|
||||
upload(glCtx, txName[1], srcRgba, sizeof srcRgba))
|
||||
{
|
||||
printf("Decoded!\n");
|
||||
}
|
||||
|
||||
emscripten_set_main_loop(tick, 0, EM_FALSE);
|
||||
emscripten_exit_with_live_runtime();
|
||||
} else {
|
||||
printf("Failed to init WebGL!\n");
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<title>Emscripten Shell</title>
|
||||
<style>
|
||||
body {background:#333; font-family:"Verdana","Helvetica Neue","Helvetica","Arial",sans-serif; margin:1em 0;}
|
||||
#canvas{position:absolute; top:0px; left:0px; border:none; margin:0; width: 100%; height: 100%; overflow: hidden; display: block;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
<script>
|
||||
var Module = {
|
||||
canvas: (function() {
|
||||
return document.getElementById("canvas");
|
||||
})()
|
||||
};
|
||||
</script>
|
||||
{{{ SCRIPT }}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* \file simple.cpp
|
||||
* Bare minimum example of using the single-file \c basisu_transcoder.cpp.
|
||||
* Opens an embedded \c .basis file to test that amalgamating the transcoder
|
||||
* worked.
|
||||
* \n
|
||||
* Compile using:
|
||||
* \code
|
||||
* cc -std=c++11 -lstdc++ simple.cpp
|
||||
* \endcode
|
||||
*
|
||||
* Example code released under a CC0 license.
|
||||
*/
|
||||
#include "../basisu_transcoder.cpp"
|
||||
|
||||
using namespace basist;
|
||||
|
||||
//********************************* Test Data ********************************/
|
||||
|
||||
/**
|
||||
* Basis Universal compressed 256x256 RGB texture source (with mipmaps).
|
||||
* \n
|
||||
* See \c testcard.png for the original. Generate using:
|
||||
* \code
|
||||
* basisu -comp_level 5 -linear -global_sel_pal -y_flip -mipmap
|
||||
* \endcode
|
||||
*/
|
||||
static uint8_t const srcRgb[] = {
|
||||
#include "testcard.basis.inc"
|
||||
};
|
||||
|
||||
//****************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Simple single-file test to test the transcoder can build and run.
|
||||
*/
|
||||
int main() {
|
||||
basisu_transcoder_init();
|
||||
|
||||
basisu_transcoder transcoder;
|
||||
if (transcoder.validate_header(srcRgb, sizeof srcRgb)) {
|
||||
basisu_file_info fileInfo;
|
||||
if (transcoder.get_file_info(srcRgb, sizeof srcRgb, fileInfo)) {
|
||||
basisu_image_info info;
|
||||
if (transcoder.get_image_info(srcRgb, sizeof srcRgb, info, 0)) {
|
||||
printf("Success (file w: %d, h: %d, mips: %d)\n",
|
||||
info.m_width, info.m_height, info.m_total_levels);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
+1043
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
+703
@@ -0,0 +1,703 @@
|
||||
0x73, 0x42, 0x13, 0x00, 0x4d, 0x00, 0xfc, 0xe8, 0x9e, 0x20, 0x00, 0x00,
|
||||
0xcb, 0xa6, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x57, 0x01, 0x1c, 0x01, 0x00, 0x00, 0xf5, 0x02, 0x00,
|
||||
0xa3, 0x02, 0x11, 0x04, 0x00, 0x00, 0x62, 0x09, 0x00, 0x73, 0x0d, 0x00,
|
||||
0x00, 0x73, 0x01, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x01, 0x40, 0x00, 0x40, 0x00, 0xe6, 0x0e, 0x00, 0x00, 0x04, 0x0a,
|
||||
0x00, 0x00, 0x47, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x80,
|
||||
0x00, 0x20, 0x00, 0x20, 0x00, 0xea, 0x18, 0x00, 0x00, 0xaf, 0x05, 0x00,
|
||||
0x00, 0x4c, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x40, 0x00,
|
||||
0x10, 0x00, 0x10, 0x00, 0x99, 0x1e, 0x00, 0x00, 0xa3, 0x01, 0x00, 0x00,
|
||||
0xd0, 0x9e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x20, 0x00, 0x08,
|
||||
0x00, 0x08, 0x00, 0x3c, 0x20, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xbc,
|
||||
0xfc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x10, 0x00, 0x04, 0x00,
|
||||
0x04, 0x00, 0xb8, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xbe, 0x4b,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x02,
|
||||
0x00, 0xd9, 0x20, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0xf6, 0x00,
|
||||
0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00,
|
||||
0xe2, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x29, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0xe5,
|
||||
0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xbd, 0xa9, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xe8, 0x20,
|
||||
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xab, 0x20, 0x40, 0x04, 0x00,
|
||||
0x42, 0x10, 0x04, 0x60, 0xe0, 0x0f, 0x2d, 0xc9, 0x4a, 0xd1, 0x13, 0x30,
|
||||
0x43, 0x06, 0x02, 0x3c, 0xa0, 0x00, 0x87, 0x60, 0x18, 0x9a, 0x97, 0xf4,
|
||||
0xc3, 0x38, 0x36, 0xbb, 0x51, 0x95, 0xe6, 0x81, 0x00, 0x0f, 0x20, 0x48,
|
||||
0x61, 0x10, 0x06, 0x6e, 0x22, 0x45, 0x60, 0xd0, 0x3b, 0x5a, 0x79, 0x03,
|
||||
0x09, 0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40, 0x08, 0x14, 0x1e, 0xec,
|
||||
0x87, 0x4b, 0x4d, 0x51, 0xc0, 0x60, 0x99, 0x42, 0xd4, 0x84, 0x63, 0x88,
|
||||
0x0e, 0x8d, 0x48, 0x59, 0xf7, 0x5c, 0xfa, 0x9c, 0x33, 0x38, 0x3a, 0x1f,
|
||||
0xd5, 0x2d, 0x85, 0x1e, 0x44, 0x54, 0x40, 0xa4, 0xc6, 0x0a, 0x88, 0xff,
|
||||
0x66, 0xcd, 0x97, 0xf1, 0x7c, 0xa3, 0xf3, 0x9c, 0xa4, 0x56, 0xcb, 0x53,
|
||||
0xd0, 0x31, 0x64, 0x65, 0x4c, 0xc8, 0xea, 0x3e, 0x50, 0x3c, 0xce, 0xe9,
|
||||
0x5a, 0xed, 0xd4, 0x06, 0xec, 0x15, 0x3d, 0xc3, 0xaf, 0xd6, 0x69, 0x6b,
|
||||
0x36, 0x72, 0x2e, 0x51, 0x8b, 0xba, 0x94, 0x33, 0xfa, 0x59, 0x4d, 0xa9,
|
||||
0xf1, 0xf4, 0x9b, 0xbe, 0x9d, 0xd1, 0x87, 0xb9, 0xcd, 0x79, 0xdc, 0x97,
|
||||
0x52, 0xf2, 0x18, 0xec, 0xe3, 0x4f, 0xae, 0xbb, 0x7d, 0x4a, 0x49, 0x11,
|
||||
0xc1, 0x7d, 0x73, 0x02, 0xff, 0xcf, 0x9b, 0x5a, 0xb5, 0x32, 0xa0, 0x92,
|
||||
0x54, 0x17, 0xa1, 0x91, 0xd1, 0x0f, 0x6c, 0x22, 0xfd, 0x3c, 0xda, 0x34,
|
||||
0xc6, 0xf1, 0x61, 0x59, 0xfe, 0x9d, 0x6a, 0x17, 0x53, 0x30, 0xeb, 0x97,
|
||||
0xa2, 0x9d, 0x8e, 0xf4, 0x35, 0xff, 0xa0, 0x21, 0x30, 0xc4, 0x04, 0x40,
|
||||
0x8c, 0x98, 0xe4, 0x23, 0xee, 0x46, 0x01, 0x22, 0x65, 0x37, 0xe4, 0xf8,
|
||||
0x2b, 0xe7, 0xa7, 0xe5, 0xbc, 0x11, 0x03, 0xe2, 0x45, 0xd8, 0x90, 0xcf,
|
||||
0x03, 0xbf, 0x33, 0x70, 0xe0, 0xfa, 0xc8, 0x80, 0xf1, 0x3c, 0x2e, 0x84,
|
||||
0xf6, 0xa5, 0x03, 0xe0, 0x98, 0xc7, 0xc3, 0x1f, 0x87, 0xc9, 0xe6, 0xaa,
|
||||
0xba, 0x31, 0xc6, 0x80, 0x31, 0xa6, 0x5e, 0xcb, 0x00, 0x02, 0xca, 0xb5,
|
||||
0xb5, 0xae, 0x2b, 0xd6, 0x9f, 0x59, 0x7d, 0x61, 0x86, 0xea, 0x79, 0xc3,
|
||||
0xfc, 0x84, 0x36, 0x44, 0xdc, 0x45, 0xac, 0xe9, 0x49, 0x8e, 0x8c, 0xc8,
|
||||
0xd5, 0x13, 0x98, 0x6c, 0xff, 0xf9, 0xbe, 0xef, 0xe4, 0x92, 0x76, 0x8e,
|
||||
0xa3, 0xb6, 0xde, 0x33, 0x96, 0x49, 0x95, 0xa0, 0x67, 0xdb, 0xb6, 0x99,
|
||||
0x59, 0x6a, 0xad, 0x7c, 0x3e, 0x1f, 0xd9, 0xce, 0x7d, 0xd4, 0x5b, 0xf7,
|
||||
0x3c, 0x5a, 0xa6, 0x1f, 0x63, 0xac, 0xb5, 0xc6, 0x14, 0xe9, 0xf6, 0x97,
|
||||
0x93, 0x52, 0xea, 0xb2, 0x2c, 0x23, 0xb9, 0x52, 0x4a, 0xbc, 0xf7, 0xf4,
|
||||
0xde, 0x97, 0x73, 0x76, 0xce, 0x39, 0xd3, 0x34, 0x89, 0x99, 0xef, 0xba,
|
||||
0x2e, 0x9c, 0x73, 0x39, 0x8e, 0x63, 0xaa, 0xba, 0x7d, 0xdf, 0xbd, 0xef,
|
||||
0xfb, 0x44, 0xa4, 0xeb, 0xba, 0xee, 0xb3, 0x16, 0x5e, 0x15, 0x84, 0x10,
|
||||
0x50, 0x8d, 0x66, 0x0e, 0x8b, 0x31, 0xc8, 0x39, 0x93, 0xdb, 0xa3, 0x29,
|
||||
0xfa, 0x00, 0xf0, 0x8c, 0xc5, 0xc5, 0xb6, 0xcc, 0x2c, 0x66, 0xb6, 0x31,
|
||||
0xc6, 0xd7, 0x5c, 0x7f, 0x76, 0xf3, 0x8c, 0x13, 0x5f, 0xcb, 0x21, 0xf8,
|
||||
0x23, 0xa2, 0x08, 0xc9, 0x54, 0x49, 0x61, 0x18, 0xe2, 0x9e, 0x34, 0x98,
|
||||
0xcd, 0x6e, 0x45, 0xf4, 0x7f, 0x80, 0xac, 0xb2, 0x49, 0x12, 0xa3, 0x81,
|
||||
0xd7, 0xde, 0xc4, 0xdf, 0x37, 0xe0, 0x3c, 0xfc, 0xe4, 0x5f, 0x3c, 0x45,
|
||||
0x44, 0x5e, 0xf6, 0xec, 0x72, 0xde, 0x70, 0x16, 0x96, 0x7d, 0x1c, 0xfb,
|
||||
0xe1, 0x6f, 0xb4, 0x66, 0x8a, 0x7f, 0x2a, 0xcd, 0x13, 0x70, 0x72, 0x22,
|
||||
0x10, 0xe3, 0x09, 0xd8, 0x44, 0x06, 0x82, 0xec, 0xee, 0x10, 0xf4, 0x10,
|
||||
0x00, 0x21, 0x05, 0x44, 0x60, 0x1c, 0x56, 0xae, 0x56, 0x90, 0x86, 0xa1,
|
||||
0x5d, 0xf2, 0x8d, 0xa4, 0x00, 0x90, 0x54, 0x63, 0x58, 0x07, 0x31, 0xbd,
|
||||
0xdd, 0x48, 0x00, 0x03, 0x49, 0xe7, 0x70, 0x90, 0x52, 0x52, 0xf9, 0x1e,
|
||||
0xa4, 0x24, 0xa0, 0x49, 0x86, 0xc0, 0x08, 0x04, 0x20, 0x04, 0x12, 0x44,
|
||||
0x8f, 0xa5, 0x6d, 0x75, 0xbc, 0xda, 0xf3, 0x01, 0xb4, 0x92, 0x5d, 0x5d,
|
||||
0x3a, 0x49, 0x3d, 0x4f, 0xcc, 0xb3, 0xe4, 0x3c, 0xd6, 0x43, 0x40, 0xe4,
|
||||
0xee, 0xd4, 0x94, 0xd7, 0x70, 0x7e, 0x73, 0x69, 0x8d, 0xf9, 0xc3, 0x4e,
|
||||
0x09, 0x04, 0xf0, 0x02, 0x1c, 0xe1, 0xf2, 0xaa, 0x4a, 0x83, 0xe7, 0x65,
|
||||
0x81, 0x40, 0x52, 0xaa, 0x50, 0x6b, 0x77, 0xaf, 0xeb, 0xfa, 0xde, 0x30,
|
||||
0x0c, 0x16, 0x41, 0xef, 0xf7, 0x86, 0xd8, 0xaf, 0x11, 0xf1, 0x36, 0xd5,
|
||||
0xd3, 0x11, 0x12, 0xdf, 0x2c, 0x56, 0x65, 0xf4, 0x8d, 0x1f, 0xd6, 0xdd,
|
||||
0x71, 0x3b, 0xad, 0xb7, 0x0c, 0xcf, 0x41, 0xd3, 0x34, 0xe5, 0x38, 0x2d,
|
||||
0xed, 0x88, 0x2c, 0x6f, 0x50, 0x5a, 0x36, 0x30, 0x79, 0xfb, 0x24, 0xbf,
|
||||
0xd7, 0xa2, 0xac, 0x29, 0xea, 0x1f, 0xff, 0x06, 0x47, 0xdf, 0xb6, 0x6e,
|
||||
0x55, 0xa5, 0xce, 0xa1, 0x98, 0x0a, 0x8a, 0xcc, 0x46, 0xaa, 0x49, 0x90,
|
||||
0x0a, 0x0a, 0x02, 0xbe, 0x9c, 0x05, 0xe0, 0xf4, 0x89, 0xcb, 0x9a, 0x6e,
|
||||
0x3c, 0xa4, 0xf9, 0xd5, 0x29, 0xbe, 0xe2, 0x7c, 0x98, 0xb4, 0x72, 0x8f,
|
||||
0xd6, 0x52, 0x2b, 0xcf, 0xaf, 0x4f, 0x8b, 0x0a, 0xe4, 0x1c, 0x98, 0x91,
|
||||
0x88, 0x48, 0xa1, 0x4a, 0xad, 0x07, 0x40, 0x79, 0x60, 0xc1, 0xdc, 0xfc,
|
||||
0x22, 0x47, 0x4e, 0xdf, 0x28, 0x4d, 0x73, 0xfa, 0x7d, 0x29, 0xff, 0xbe,
|
||||
0x4f, 0xef, 0xfc, 0xaf, 0xb6, 0xfd, 0x79, 0xb2, 0x02, 0x22, 0x02, 0x04,
|
||||
0x6f, 0x34, 0x04, 0x20, 0x28, 0x00, 0x7f, 0xe4, 0xe7, 0x2d, 0xf4, 0xb2,
|
||||
0x70, 0x02, 0x29, 0x93, 0x89, 0x45, 0x19, 0x8d, 0x4c, 0x36, 0xb9, 0x81,
|
||||
0x2b, 0xbc, 0x57, 0x46, 0x07, 0x70, 0x1c, 0x72, 0x07, 0x83, 0xe1, 0x91,
|
||||
0xb2, 0x5b, 0x94, 0x92, 0x27, 0x1f, 0x98, 0xbc, 0xb1, 0x2d, 0x05, 0x00,
|
||||
0x00, 0xc0, 0x7f, 0x45, 0x97, 0xd7, 0x2e, 0x35, 0x47, 0x07, 0x11, 0x27,
|
||||
0x1f, 0x27, 0x45, 0x22, 0xe2, 0x54, 0xa9, 0xd4, 0x3c, 0xcd, 0x56, 0x5c,
|
||||
0x4a, 0x5d, 0x1c, 0x24, 0xc6, 0x65, 0xe3, 0xb2, 0x0f, 0x87, 0xea, 0x7b,
|
||||
0xd1, 0xbd, 0x2d, 0xd6, 0xab, 0x8f, 0x3f, 0x80, 0xe3, 0x4a, 0xc4, 0x28,
|
||||
0x49, 0xa7, 0x91, 0xf5, 0x6d, 0x12, 0x8e, 0xc3, 0xcd, 0xcd, 0xf6, 0x0f,
|
||||
0x0c, 0x88, 0x88, 0x0f, 0x0f, 0xaa, 0xaa, 0x0f, 0x0f, 0x6a, 0xaa, 0x0f,
|
||||
0x0f, 0x69, 0xaa, 0x0f, 0x0f, 0xfb, 0x2a, 0x0b, 0x03, 0xff, 0x78, 0x0b,
|
||||
0x01, 0xf9, 0xfa, 0x0a, 0x09, 0xfa, 0xfa, 0x0a, 0x09, 0xea, 0xbf, 0x2e,
|
||||
0x00, 0x80, 0x40, 0xed, 0xff, 0x15, 0x00, 0xe0, 0xeb, 0x15, 0x14, 0xea,
|
||||
0xed, 0x15, 0x14, 0xec, 0xf5, 0x15, 0x14, 0x6c, 0x75, 0x55, 0x35, 0x75,
|
||||
0x75, 0x75, 0x75, 0xb5, 0xff, 0x5f, 0x5d, 0x5d, 0xfd, 0x57, 0x55, 0x55,
|
||||
0x45, 0x7c, 0x8e, 0x98, 0xfc, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xa9, 0xab, 0xab, 0x37, 0xdc, 0xfb, 0x9b, 0x96, 0x52, 0x06, 0x00,
|
||||
0x27, 0x1d, 0xbe, 0x74, 0x7c, 0xdd, 0xb8, 0xd8, 0xd1, 0x73, 0x58, 0xab,
|
||||
0x52, 0xfa, 0x08, 0xff, 0xaa, 0x2e, 0xa4, 0xaa, 0xaa, 0xae, 0xa6, 0xac,
|
||||
0xab, 0xaa, 0xaa, 0x0e, 0x1f, 0x44, 0xaa, 0xaa, 0xaa, 0x3f, 0x87, 0xaa,
|
||||
0xaa, 0xea, 0x3f, 0x62, 0x47, 0x5d, 0x5d, 0xfd, 0x5f, 0x55, 0x55, 0x95,
|
||||
0x7f, 0x75, 0x75, 0xf5, 0x5f, 0x20, 0x68, 0xd9, 0x38, 0x58, 0x37, 0x01,
|
||||
0x82, 0x83, 0xbe, 0xc4, 0x0d, 0x7e, 0x7e, 0xd6, 0xfe, 0xfe, 0xfe, 0xd6,
|
||||
0xfe, 0xf6, 0xf6, 0xf6, 0xfe, 0xfe, 0xd6, 0xfe, 0xfe, 0x7e, 0x56, 0x7e,
|
||||
0x7e, 0xd2, 0xdf, 0xde, 0x4f, 0xf5, 0xfe, 0xfe, 0x5f, 0xf5, 0xfe, 0xfe,
|
||||
0x5f, 0x29, 0x71, 0x49, 0x55, 0xb5, 0xbb, 0x5b, 0x55, 0x15, 0x1e, 0x3e,
|
||||
0x55, 0x15, 0x1e, 0x3e, 0x4d, 0x15, 0x1e, 0xbe, 0x03, 0x07, 0x07, 0x07,
|
||||
0x07, 0x06, 0x06, 0x26, 0x3f, 0x78, 0x05, 0x0c, 0x1c, 0x2c, 0x0c, 0x0c,
|
||||
0x0c, 0xac, 0x0e, 0x0d, 0x0c, 0xac, 0x0e, 0x0c, 0x08, 0xa8, 0x5e, 0x3c,
|
||||
0xeb, 0x40, 0x02, 0x00, 0xa8, 0x1e, 0xf4, 0x00, 0x00, 0x80, 0x7c, 0x01,
|
||||
0x00, 0x80, 0xfe, 0x0f, 0x5e, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x04, 0x04,
|
||||
0xf8, 0x07, 0x04, 0x04, 0x58, 0x9d, 0x07, 0x5b, 0x00, 0x00, 0x00, 0xc5,
|
||||
0x08, 0x7f, 0x00, 0x00, 0x80, 0xa0, 0x01, 0x00, 0x00, 0xa1, 0x2f, 0x9e,
|
||||
0x08, 0xcc, 0x2a, 0x45, 0xb1, 0x49, 0xd3, 0xa0, 0xd7, 0xf1, 0x49, 0x55,
|
||||
0x4d, 0x55, 0xbd, 0xa3, 0x73, 0xd0, 0x5a, 0x43, 0x43, 0x43, 0x5b, 0x43,
|
||||
0x43, 0x5b, 0xbd, 0xaf, 0x93, 0xf5, 0xf5, 0xf5, 0x75, 0xc4, 0x95, 0x19,
|
||||
0x75, 0x75, 0xf5, 0x80, 0xf4, 0xe0, 0x29, 0xe2, 0xf7, 0xef, 0xd3, 0xe6,
|
||||
0x63, 0x04, 0xd2, 0x02, 0x89, 0x1f, 0x1e, 0x54, 0x55, 0x1f, 0x1e, 0x54,
|
||||
0xd5, 0x1e, 0x1e, 0x54, 0xd3, 0x1e, 0x1e, 0xf4, 0xf5, 0x13, 0x14, 0xf4,
|
||||
0xf5, 0x59, 0x82, 0x82, 0x7e, 0x7e, 0xc0, 0x02, 0xde, 0xff, 0xc0, 0x82,
|
||||
0xca, 0xbe, 0x80, 0x80, 0xc0, 0xbe, 0x80, 0x80, 0xc0, 0xbf, 0x80, 0x80,
|
||||
0xd0, 0xbf, 0xc1, 0x80, 0xc0, 0x7f, 0xf1, 0x2d, 0x3a, 0x30, 0x30, 0xf4,
|
||||
0x3f, 0x30, 0x30, 0xb4, 0x36, 0x30, 0x30, 0xb0, 0x3a, 0x20, 0x20, 0xb0,
|
||||
0x5a, 0x3c, 0x27, 0x20, 0x60, 0xa5, 0x2a, 0x20, 0x20, 0xb9, 0x2b, 0x22,
|
||||
0x26, 0xb9, 0x9e, 0x89, 0x89, 0x49, 0xae, 0xaf, 0x0a, 0x48, 0xae, 0xad,
|
||||
0x0a, 0x08, 0x0c, 0xac, 0x0e, 0x0c, 0x0c, 0xac, 0x0d, 0x0d, 0x0c, 0xfc,
|
||||
0x0f, 0x0d, 0x0c, 0x14, 0xdf, 0xfe, 0x17, 0x18, 0x30, 0x28, 0xfe, 0x05,
|
||||
0x04, 0x04, 0xf6, 0x05, 0x04, 0x04, 0xfe, 0x85, 0x04, 0x04, 0xfe, 0x81,
|
||||
0x00, 0x00, 0x0e, 0x5e, 0xfe, 0x03, 0x00, 0x04, 0x48, 0x34, 0x7c, 0x81,
|
||||
0x00, 0x00, 0xa0, 0x0a, 0x00, 0x10, 0xb0, 0x1a, 0x10, 0x10, 0xa0, 0x1b,
|
||||
0x14, 0x10, 0xa0, 0x19, 0x04, 0x04, 0xa4, 0x0e, 0x04, 0x04, 0xa4, 0x0e,
|
||||
0x0c, 0x0c, 0xac, 0x0e, 0x0c, 0x0c, 0xad, 0x0e, 0x08, 0x08, 0xcc, 0x8b,
|
||||
0x17, 0x76, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x81,
|
||||
0x21, 0xff, 0x01, 0x81, 0x00, 0xfe, 0x01, 0x80, 0x80, 0xfe, 0x01, 0x80,
|
||||
0xc0, 0x8b, 0x1b, 0xf8, 0x87, 0x06, 0x06, 0xfe, 0x07, 0x06, 0x0e, 0xfe,
|
||||
0x0f, 0x06, 0x06, 0xfe, 0xaf, 0x06, 0x06, 0x7e, 0xaf, 0x06, 0x04, 0x6e,
|
||||
0x3f, 0x06, 0x06, 0x26, 0xdf, 0x06, 0x06, 0x26, 0x07, 0x06, 0x06, 0x56,
|
||||
0x24, 0xea, 0x00, 0x40, 0xc0, 0x70, 0x40, 0xc0, 0xd0, 0x70, 0x40, 0x80,
|
||||
0x90, 0x60, 0x60, 0x90, 0x80, 0x40, 0x70, 0xd0, 0xc0, 0x40, 0x70, 0xc0,
|
||||
0x40, 0x00, 0xd0, 0x80, 0x00, 0x00, 0x1c, 0xe1, 0x37, 0x30, 0x00, 0x10,
|
||||
0x10, 0x10, 0x10, 0x90, 0x10, 0x10, 0x10, 0x90, 0x3a, 0x00, 0x00, 0xb4,
|
||||
0x1b, 0x00, 0x00, 0xc0, 0x1b, 0x00, 0x40, 0x80, 0x0b, 0xdd, 0x0f, 0x01,
|
||||
0x00, 0x10, 0x30, 0x80, 0xf0, 0x17, 0x00, 0xc2, 0x1e, 0xdd, 0x70, 0x20,
|
||||
0x00, 0x00, 0x00, 0x61, 0xfb, 0x60, 0x2d, 0x07, 0x10, 0x18, 0x50, 0x00,
|
||||
0x08, 0x18, 0x50, 0x08, 0x08, 0x08, 0x58, 0x3d, 0x18, 0x06, 0x07, 0x05,
|
||||
0x04, 0x40, 0x03, 0x01, 0x00, 0x1c, 0xa4, 0x57, 0x02, 0x02, 0x02, 0xda,
|
||||
0xd4, 0xc0, 0xc4, 0xc0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc1, 0x8b, 0x81, 0x81,
|
||||
0x81, 0x83, 0x00, 0x81, 0x81, 0x03, 0x00, 0x81, 0x83, 0x06, 0x00, 0x80,
|
||||
0x83, 0x16, 0x00, 0x80, 0xd7, 0x57, 0x00, 0x00, 0xbc, 0xfe, 0x03, 0x00,
|
||||
0xe8, 0xfe, 0x03, 0x00, 0x01, 0xfe, 0x43, 0x02, 0x03, 0xfe, 0x03, 0x02,
|
||||
0x02, 0xfe, 0x03, 0x02, 0x06, 0xbe, 0x03, 0x03, 0x56, 0xbf, 0x03, 0x03,
|
||||
0x57, 0xff, 0xab, 0xc0, 0xc0, 0xd0, 0xff, 0xc5, 0xf5, 0x60, 0x60, 0xe0,
|
||||
0x7f, 0x60, 0xe0, 0xe0, 0x7f, 0x60, 0x60, 0xe0, 0x6d, 0x60, 0x50, 0xa4,
|
||||
0x6d, 0x70, 0x70, 0xe8, 0x7f, 0x70, 0x70, 0xf0, 0x7f, 0x02, 0x0e, 0x04,
|
||||
0xf0, 0x0f, 0x09, 0x00, 0xf0, 0x0f, 0x08, 0x08, 0x58, 0x7d, 0xf0, 0xb9,
|
||||
0x1a, 0x10, 0x10, 0x70, 0x1b, 0x18, 0x18, 0x78, 0x1b, 0x09, 0x14, 0xf8,
|
||||
0x1f, 0x1c, 0x1c, 0xbc, 0xf9, 0x87, 0x06, 0x07, 0xf7, 0x87, 0x02, 0x05,
|
||||
0x75, 0x83, 0x06, 0x00, 0x78, 0x03, 0x00, 0x00, 0x70, 0x09, 0x00, 0x00,
|
||||
0x08, 0xf8, 0x15, 0x50, 0x6b, 0x39, 0x00, 0x00, 0x40, 0xc3, 0x81, 0x00,
|
||||
0xc0, 0xc1, 0x80, 0x40, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
|
||||
0xd0, 0xc0, 0xc0, 0xd0, 0xe0, 0xe0, 0xd0, 0xc0, 0xc0, 0xc0, 0xd0, 0xee,
|
||||
0xc1, 0xc0, 0xe0, 0xed, 0x07, 0x1b, 0x1c, 0x9e, 0xfc, 0x17, 0x1e, 0x16,
|
||||
0xfe, 0x1f, 0x4e, 0x66, 0xfe, 0x4f, 0x4c, 0x44, 0x74, 0x4f, 0x4f, 0x49,
|
||||
0x51, 0x4f, 0x4f, 0x49, 0x49, 0x57, 0x4f, 0x49, 0x49, 0x3f, 0x68, 0xce,
|
||||
0x26, 0xad, 0xef, 0x53, 0x40, 0xaa, 0xaa, 0x77, 0x60, 0xa0, 0xaf, 0x6f,
|
||||
0x60, 0xa0, 0xaf, 0xaf, 0x6c, 0xac, 0xaf, 0x6f, 0x6e, 0xa5, 0xa1, 0xd2,
|
||||
0x8b, 0x1f, 0x04, 0x2d, 0x7f, 0xbc, 0xbd, 0x7d, 0x78, 0x96, 0x04, 0x1e,
|
||||
0x2b, 0x95, 0x94, 0x2e, 0x0f, 0x94, 0x5b, 0x81, 0xb2, 0xd7, 0xb3, 0xeb,
|
||||
0xe8, 0x3a, 0xbd, 0xb8, 0xb8, 0xb8, 0xd8, 0x38, 0xfb, 0x7d, 0xfe, 0xea,
|
||||
0xea, 0xea, 0x5f, 0x5a, 0x55, 0x55, 0xfd, 0x6f, 0x9c, 0xe9, 0x29, 0xa6,
|
||||
0xac, 0x22, 0xec, 0x34, 0x45, 0x22, 0x6f, 0xd5, 0x87, 0x91, 0x41, 0x6a,
|
||||
0x45, 0x45, 0x25, 0x68, 0x45, 0x45, 0x65, 0x75, 0x45, 0x45, 0x45, 0x15,
|
||||
0x12, 0x19, 0x6c, 0x0a, 0x52, 0x51, 0x59, 0x09, 0x56, 0x55, 0x55, 0xc9,
|
||||
0xe1, 0xaa, 0xaa, 0xaa, 0x94, 0xf7, 0x08, 0xff, 0x01, 0x8e, 0xa5, 0x74,
|
||||
0x11, 0x76, 0x53, 0xde, 0x75, 0xac, 0x96, 0x1b, 0xe7, 0xfe, 0xab, 0xaa,
|
||||
0xac, 0xfe, 0xa7, 0xae, 0xac, 0x56, 0xaf, 0xae, 0xae, 0x0e, 0x12, 0xf5,
|
||||
0xe2, 0xea, 0xea, 0xe2, 0x87, 0x33, 0x95, 0x95, 0x95, 0xeb, 0x65, 0x65,
|
||||
0x65, 0xe5, 0xc1, 0x52, 0x65, 0x45, 0x45, 0x65, 0x48, 0x3b, 0xa4, 0x29,
|
||||
0x58, 0x51, 0x51, 0xe9, 0x18, 0xd3, 0xad, 0x6c, 0x1d, 0xdd, 0x8d, 0x62,
|
||||
0xc7, 0xc7, 0x8e, 0x36, 0xce, 0x87, 0xaa, 0x2a, 0x66, 0xe6, 0xf4, 0xcd,
|
||||
0xf4, 0x34, 0x16, 0xd8, 0x3f, 0x90, 0x15, 0xb8, 0xa9, 0xf0, 0xf0, 0xa0,
|
||||
0x20, 0x30, 0x57, 0x3c, 0xaf, 0x6a, 0x25, 0x20, 0xb0, 0x7a, 0x21, 0x2a,
|
||||
0x40, 0x57, 0x2f, 0x4e, 0x07, 0xf6, 0x2f, 0x04, 0x06, 0xfe, 0x0f, 0x0e,
|
||||
0x0e, 0xde, 0x0d, 0x0e, 0x0e, 0x3c, 0x43, 0x01, 0x03, 0x06, 0x12, 0x80,
|
||||
0x83, 0x0e, 0x5a, 0x80, 0x83, 0x5e, 0x48, 0x08, 0x38, 0xd0, 0x40, 0x2b,
|
||||
0x70, 0xd0, 0x41, 0x1f, 0x74, 0xd0, 0x02, 0x07, 0x7c, 0xd0, 0x03, 0x3d,
|
||||
0x3c, 0x40, 0x41, 0x2d, 0x28, 0x40, 0x41, 0x09, 0x28, 0x60, 0xc0, 0x29,
|
||||
0x30, 0x60, 0xd0, 0x20, 0x81, 0x01, 0x03, 0x05, 0x83, 0x21, 0x41, 0x01,
|
||||
0x85, 0x21, 0xe1, 0x00, 0x0c, 0x25, 0x61, 0x00, 0x0c, 0x45, 0x61, 0x00,
|
||||
0x0e, 0x43, 0x41, 0x00, 0x0a, 0x4a, 0x61, 0x01, 0x1a, 0x8e, 0x43, 0x01,
|
||||
0xd0, 0x34, 0x0e, 0x02, 0xd1, 0x24, 0x0a, 0x02, 0x60, 0x24, 0x0c, 0x06,
|
||||
0xe0, 0xa0, 0x05, 0x05, 0xa0, 0x2c, 0x07, 0x01, 0x28, 0x0d, 0x07, 0x01,
|
||||
0x24, 0x0c, 0x06, 0x03, 0x34, 0x18, 0x0c, 0x0a, 0x14, 0x05, 0x83, 0x21,
|
||||
0x41, 0x21, 0x81, 0x01, 0xe3, 0x20, 0x81, 0x01, 0x25, 0x60, 0xa0, 0x01,
|
||||
0xc5, 0xec, 0x1a, 0x10, 0x34, 0x1c, 0x0a, 0x28, 0x3c, 0x3c, 0x28, 0x29,
|
||||
0x3d, 0x3d, 0xa9, 0x2b, 0x30, 0x33, 0x70, 0x65, 0x3f, 0xa6, 0xea, 0x6f,
|
||||
0xef, 0x3f, 0xe8, 0x56, 0xfd, 0xef, 0xef, 0x07, 0xfc, 0xef, 0xef, 0x03,
|
||||
0xfc, 0xff, 0xfe, 0x7a, 0x40, 0xff, 0xef, 0xef, 0x55, 0xff, 0xef, 0xef,
|
||||
0x54, 0xff, 0xfe, 0xfe, 0x01, 0xdb, 0x01, 0x75, 0x68, 0xfa, 0xee, 0xe3,
|
||||
0x70, 0xba, 0xae, 0x23, 0x40, 0xba, 0x8e, 0x81, 0x07, 0x88, 0xfe, 0x23,
|
||||
0x00, 0x00, 0xd2, 0x2d, 0x00, 0x20, 0xc0, 0x0d, 0xd2, 0x6f, 0x72, 0x63,
|
||||
0x3c, 0xeb, 0x8d, 0xc9, 0xdd, 0x8d, 0xaa, 0xe2, 0x99, 0x7f, 0xd8, 0xd8,
|
||||
0x38, 0x39, 0xd9, 0xd8, 0x78, 0x98, 0xd9, 0x78, 0xf8, 0x9f, 0xdc, 0x18,
|
||||
0xf8, 0x9f, 0x1e, 0x1a, 0xf8, 0xff, 0x1f, 0x18, 0xf8, 0xfd, 0x1d, 0x18,
|
||||
0xf8, 0xc7, 0xff, 0xc0, 0xd0, 0xf4, 0xff, 0xc0, 0xc6, 0xe4, 0xff, 0xc3,
|
||||
0xc6, 0xcc, 0xff, 0xc8, 0xcc, 0xc8, 0xff, 0xd0, 0xef, 0xc0, 0xfe, 0xfe,
|
||||
0x7f, 0xc0, 0xfe, 0xfe, 0x7f, 0xd5, 0xdf, 0xde, 0x5f, 0x45, 0xf2, 0xb7,
|
||||
0xf7, 0x57, 0xf2, 0xa7, 0xf7, 0xf7, 0xf7, 0xa7, 0xf3, 0xf3, 0x23, 0x51,
|
||||
0x3b, 0xf8, 0x26, 0x90, 0xfb, 0xfd, 0x55, 0xfd, 0xff, 0xf9, 0xd1, 0xf9,
|
||||
0x13, 0x7f, 0x7f, 0x7a, 0x7f, 0xb8, 0x1b, 0xd5, 0x09, 0x6b, 0x32, 0xdd,
|
||||
0xff, 0xd7, 0x2a, 0x05, 0x28, 0x08, 0x9b, 0x26, 0x42, 0xe8, 0xab, 0x3b,
|
||||
0x21, 0x20, 0x30, 0x28, 0x89, 0xc0, 0x02, 0x19, 0x28, 0x30, 0x50, 0xd4,
|
||||
0x21, 0x0f, 0x5a, 0x40, 0x00, 0x0e, 0x1a, 0x50, 0x60, 0x3d, 0xfb, 0x28,
|
||||
0x0d, 0x0c, 0x18, 0x24, 0xe9, 0x3e, 0x96, 0x98, 0xf0, 0xe0, 0x80, 0x80,
|
||||
0xa0, 0xe0, 0xa1, 0x04, 0x32, 0xe0, 0xa3, 0x26, 0x3a, 0xf0, 0xe3, 0x6e,
|
||||
0x7a, 0x68, 0xf2, 0xdf, 0x41, 0x07, 0xfd, 0xbf, 0x80, 0x07, 0xfd, 0xf5,
|
||||
0x05, 0x05, 0x35, 0xe0, 0xbf, 0xe3, 0x20, 0xe0, 0xee, 0xe3, 0x60, 0x80,
|
||||
0xb6, 0xe3, 0x00, 0x00, 0xb2, 0xf7, 0x00, 0xc0, 0x83, 0x74, 0x0b, 0x00,
|
||||
0x08, 0x70, 0x83, 0x04, 0x40, 0x81, 0x83, 0x06, 0xc2, 0x1d, 0x16, 0x3f,
|
||||
0x58, 0x95, 0x90, 0x92, 0x5a, 0x97, 0x14, 0x13, 0xd9, 0x97, 0x14, 0x13,
|
||||
0xc3, 0xbf, 0xf0, 0xb0, 0xf0, 0xff, 0xe4, 0xf0, 0xe0, 0xbf, 0xe0, 0xa1,
|
||||
0xe2, 0xbf, 0xa0, 0xdd, 0xc2, 0xaf, 0x81, 0x89, 0xc8, 0x7f, 0x80, 0x80,
|
||||
0xc1, 0x3f, 0x00, 0x00, 0xe5, 0x3f, 0x05, 0x05, 0xc5, 0xf8, 0x0f, 0x09,
|
||||
0x47, 0xf3, 0x0f, 0x06, 0x43, 0x02, 0x09, 0x06, 0x43, 0x03, 0x0c, 0x4a,
|
||||
0xc3, 0x01, 0x06, 0x4b, 0x8b, 0x01, 0x00, 0x48, 0xeb, 0x61, 0x16, 0x9a,
|
||||
0x4d, 0xec, 0x10, 0xb4, 0xbd, 0x28, 0x60, 0xa4, 0xbc, 0x6c, 0x28, 0xbe,
|
||||
0xbe, 0x28, 0x28, 0xbe, 0xbe, 0xb8, 0xb9, 0xbe, 0xbe, 0xbe, 0xf8, 0x39,
|
||||
0xb3, 0x82, 0x59, 0xce, 0x7e, 0x7d, 0x4d, 0xa3, 0xf0, 0x4b, 0x04, 0xa6,
|
||||
0x03, 0x66, 0xe0, 0xe1, 0xab, 0xaa, 0xe8, 0xe9, 0xab, 0x28, 0xfa, 0xfa,
|
||||
0xfa, 0x28, 0xfa, 0xfa, 0xfa, 0x58, 0x9c, 0xbe, 0xbe, 0x3e, 0x94, 0x83,
|
||||
0xe5, 0xaa, 0xaa, 0x2a, 0xc1, 0xca, 0x8a, 0x0a, 0xc1, 0xe2, 0xfb, 0x97,
|
||||
0x97, 0x97, 0x96, 0xe6, 0x97, 0x97, 0x97, 0xe6, 0x96, 0x96, 0x96, 0x50,
|
||||
0xa7, 0x34, 0x04, 0x54, 0xa7, 0x36, 0x06, 0x54, 0x27, 0x2c, 0x2c, 0x5c,
|
||||
0x17, 0x34, 0x2c, 0x54, 0x07, 0x54, 0x2c, 0x57, 0x0f, 0x54, 0x24, 0x55,
|
||||
0x37, 0x04, 0x54, 0x57, 0x34, 0x14, 0x5c, 0x6f, 0x0a, 0x0d, 0x05, 0xd7,
|
||||
0x2d, 0x2d, 0x2d, 0xd7, 0x7d, 0x7d, 0x7d, 0xd3, 0xfc, 0xfd, 0xff, 0x01,
|
||||
0xde, 0xdf, 0xff, 0x81, 0x0e, 0x06, 0x01, 0x0d, 0xfa, 0xfc, 0x7c, 0xfa,
|
||||
0x49, 0xe0, 0x3a, 0x3c, 0xbc, 0x6a, 0x2a, 0x3c, 0xbc, 0x6a, 0x1a, 0x34,
|
||||
0xde, 0xc2, 0x3f, 0x34, 0x5d, 0xc7, 0x3f, 0x14, 0x54, 0x77, 0xb7, 0xc0,
|
||||
0x23, 0xa5, 0x5c, 0x5d, 0xf1, 0xb7, 0xf7, 0x97, 0x18, 0xe1, 0x6f, 0x75,
|
||||
0xc4, 0xb7, 0xcd, 0x87, 0x87, 0xaa, 0xaa, 0xec, 0x23, 0x0f, 0x0f, 0xa5,
|
||||
0xa5, 0x10, 0x58, 0xa0, 0x09, 0x1f, 0x50, 0x40, 0x09, 0x1b, 0x48, 0x40,
|
||||
0x01, 0x33, 0x60, 0x20, 0x81, 0xa3, 0xa2, 0x22, 0x80, 0xa7, 0xa6, 0xa6,
|
||||
0xfe, 0xaf, 0xae, 0xae, 0x2e, 0x2f, 0xaf, 0xae, 0xae, 0x1e, 0xfe, 0xa9,
|
||||
0xa9, 0xa9, 0xff, 0xab, 0xb5, 0xb5, 0xff, 0xab, 0xd5, 0xb5, 0x25, 0xc6,
|
||||
0x1e, 0xdb, 0x14, 0x69, 0x69, 0x19, 0x14, 0x69, 0x69, 0x14, 0x56, 0x16,
|
||||
0x0a, 0xb5, 0x5c, 0x2a, 0xb3, 0x51, 0xb3, 0x31, 0x8a, 0x54, 0xb7, 0x8a,
|
||||
0xa1, 0x11, 0x68, 0x5a, 0xa7, 0x2b, 0x82, 0xe9, 0xd2, 0xa2, 0xd4, 0xba,
|
||||
0xb2, 0xaa, 0x6a, 0x98, 0x3a, 0x58, 0xec, 0x88, 0x12, 0xa6, 0xf6, 0x5a,
|
||||
0x70, 0x3f, 0xff, 0x32, 0x86, 0xd6, 0xd7, 0x83, 0x82, 0xf5, 0x89, 0xd1,
|
||||
0xc9, 0x0a, 0x05, 0x83, 0xd5, 0x0b, 0x53, 0x81, 0xd5, 0x81, 0xd3, 0x8b,
|
||||
0x55, 0x01, 0xd1, 0x8b, 0xd5, 0x01, 0x81, 0x8b, 0x7d, 0x1c, 0x1c, 0x1c,
|
||||
0xfc, 0x1f, 0x1c, 0x18, 0xbc, 0x0f, 0x1c, 0x7c, 0xdc, 0x05, 0x1c, 0x74,
|
||||
0xfc, 0x57, 0x54, 0x44, 0xfc, 0xd2, 0xc0, 0x41, 0xfe, 0x93, 0xc0, 0x80,
|
||||
0xfd, 0x83, 0x82, 0x42, 0xf9, 0xeb, 0x12, 0x05, 0xd3, 0xd3, 0xab, 0x7f,
|
||||
0x93, 0xb2, 0xb5, 0x7b, 0xf9, 0x3f, 0xf4, 0x3b, 0xf0, 0xbf, 0xb6, 0x76,
|
||||
0xf5, 0x7f, 0xb6, 0x76, 0xf5, 0x3f, 0x36, 0x36, 0x33, 0x33, 0x63, 0x4e,
|
||||
0x4e, 0x36, 0x36, 0x4e, 0x4e, 0x66, 0x16, 0x0e, 0x06, 0x06, 0x06, 0x06,
|
||||
0xde, 0x26, 0x07, 0x06, 0x3e, 0x6e, 0x07, 0x34, 0xa6, 0x56, 0x07, 0x34,
|
||||
0xa4, 0x2c, 0xbf, 0xb8, 0x03, 0x20, 0x20, 0xa0, 0x4a, 0x01, 0x01, 0x81,
|
||||
0x2b, 0x03, 0x81, 0x80, 0xff, 0x91, 0x99, 0x91, 0xff, 0x81, 0xdf, 0xa1,
|
||||
0xff, 0x05, 0x3b, 0xc1, 0x7f, 0x11, 0x13, 0x83, 0x5f, 0x53, 0x53, 0x29,
|
||||
0xd5, 0x91, 0x54, 0x31, 0x50, 0xbd, 0x5c, 0x11, 0x50, 0x7d, 0x4d, 0x52,
|
||||
0x60, 0x75, 0x6c, 0x72, 0x70, 0x68, 0x68, 0x70, 0x72, 0x6c, 0x78, 0xf8,
|
||||
0x5a, 0xb0, 0x2f, 0xf4, 0xcb, 0x5a, 0x9e, 0x05, 0x70, 0xaa, 0xd4, 0x7f,
|
||||
0xbf, 0x8c, 0x44, 0xc0, 0xcc, 0x8c, 0x8d, 0xfd, 0xcf, 0x9c, 0x3c, 0xfc,
|
||||
0x0f, 0xfc, 0x0e, 0xad, 0x0e, 0x58, 0x98, 0x7d, 0xb9, 0x23, 0x26, 0x26,
|
||||
0xaa, 0x42, 0x66, 0x06, 0xee, 0x83, 0x62, 0x22, 0xaa, 0x02, 0x00, 0x40,
|
||||
0x0a, 0xcc, 0x9b, 0xc4, 0xd5, 0x9d, 0xef, 0xca, 0xa7, 0x56, 0xc1, 0x78,
|
||||
0x7a, 0xc5, 0x31, 0x0b, 0xb2, 0x0f, 0xd7, 0x8c, 0x98, 0x8d, 0x9b, 0x55,
|
||||
0xed, 0x17, 0x53, 0xb5, 0xe3, 0x56, 0x5b, 0x7d, 0xf5, 0xb5, 0x79, 0xf6,
|
||||
0xec, 0x50, 0x05, 0x77, 0x40, 0xde, 0xde, 0xde, 0x1e, 0x1c, 0x1e, 0xd3,
|
||||
0xc2, 0xf1, 0xd3, 0xff, 0xff, 0x82, 0x82, 0xff, 0x74, 0x0b, 0x80, 0x3b,
|
||||
0x20, 0x20, 0xa0, 0x4a, 0x20, 0x20, 0x20, 0x2e, 0xa5, 0xa1, 0x20, 0xab,
|
||||
0x80, 0x80, 0x80, 0x9a, 0xaa, 0x5f, 0x50, 0x00, 0x0a, 0x2e, 0x91, 0x91,
|
||||
0xc8, 0x7e, 0xdc, 0x0e, 0x0e, 0x1c, 0xec, 0x0e, 0x0d, 0xd4, 0x8e, 0x02,
|
||||
0x94, 0x6a, 0xfd, 0x03, 0xec, 0xaa, 0xae, 0x06, 0x88, 0x98, 0xa0, 0xfb,
|
||||
0xef, 0xd0, 0xc0, 0xff, 0xff, 0xc0, 0xd0, 0xef, 0xa0, 0x79, 0x94, 0xde,
|
||||
0x5c, 0x8a, 0xa8, 0x03, 0x41, 0x43, 0x4f, 0x5c, 0xc5, 0xca, 0x0a, 0x09,
|
||||
0xda, 0xaa, 0x81, 0x42, 0xc5, 0xaa, 0x80, 0xe9, 0x85, 0xc4, 0x41, 0x01,
|
||||
0xc1, 0xdb, 0x81, 0x6d, 0xa3, 0x8a, 0xc3, 0x5f, 0xf1, 0x8b, 0x8a, 0xc4,
|
||||
0x55, 0xc9, 0xe7, 0x8f, 0xa7, 0x2e, 0x45, 0x8c, 0xac, 0x91, 0x68, 0x94,
|
||||
0x81, 0x56, 0xf9, 0x49, 0x5c, 0x60, 0x49, 0xb7, 0x3e, 0x79, 0x8a, 0x6e,
|
||||
0x42, 0x5d, 0x1b, 0xa5, 0x91, 0x19, 0xa8, 0x3c, 0x76, 0x09, 0x7f, 0x0a,
|
||||
0x5b, 0x03, 0x0c, 0x48, 0xbc, 0xd2, 0xb3, 0x5c, 0x89, 0xab, 0xcc, 0x23,
|
||||
0xb5, 0xba, 0x60, 0x3a, 0xa0, 0x4c, 0x08, 0xc9, 0xc2, 0xbe, 0x7a, 0x71,
|
||||
0xf4, 0xee, 0x2a, 0x88, 0xfb, 0xa1, 0x71, 0xd6, 0x71, 0x1c, 0xbf, 0xd7,
|
||||
0xe7, 0xfb, 0x3c, 0x97, 0xfb, 0x93, 0xbb, 0xeb, 0xe5, 0x8f, 0xa9, 0x25,
|
||||
0x69, 0xb5, 0xc6, 0xb6, 0x81, 0x08, 0xfe, 0x02, 0xcd, 0xa4, 0xee, 0x15,
|
||||
0x44, 0xb2, 0x88, 0xa0, 0x88, 0x7f, 0x8b, 0xf4, 0xb7, 0x10, 0x5d, 0x54,
|
||||
0x5c, 0x9c, 0x1d, 0x5c, 0xa4, 0x28, 0xe8, 0x56, 0xc1, 0xe2, 0xe0, 0xe2,
|
||||
0xa2, 0x52, 0x28, 0x0a, 0x59, 0xa4, 0x28, 0xa8, 0x88, 0x6e, 0xba, 0xa4,
|
||||
0x0e, 0xc5, 0xe2, 0x24, 0x6e, 0xb7, 0xb8, 0x88, 0x0e, 0x25, 0x18, 0xfb,
|
||||
0x07, 0x6b, 0x85, 0xfc, 0xbd, 0xa4, 0x97, 0xbb, 0x3c, 0xc9, 0x3d, 0xdf,
|
||||
0xe7, 0xf9, 0xbe, 0xc9, 0x85, 0x77, 0xb0, 0xf3, 0x7b, 0x7e, 0xcf, 0x63,
|
||||
0xaf, 0x2a, 0xed, 0x24, 0xad, 0x30, 0xd6, 0x58, 0x6b, 0x8b, 0xda, 0x3b,
|
||||
0x62, 0x1d, 0xd3, 0x8e, 0xad, 0x96, 0x16, 0x69, 0xc2, 0xb8, 0x80, 0x10,
|
||||
0x6b, 0x51, 0x5b, 0xc7, 0x3a, 0x63, 0x0b, 0x1d, 0x14, 0xa3, 0xd4, 0x56,
|
||||
0xf7, 0x30, 0x54, 0x95, 0x29, 0x75, 0x01, 0xe3, 0x22, 0xea, 0x06, 0xc6,
|
||||
0xb8, 0x8f, 0x48, 0x1b, 0x4b, 0x8a, 0xd8, 0xfe, 0x30, 0xd1, 0x61, 0x88,
|
||||
0x65, 0x4a, 0x18, 0x65, 0x5c, 0x40, 0xa9, 0x65, 0x08, 0x26, 0xa8, 0xeb,
|
||||
0x09, 0x46, 0x64, 0x50, 0x71, 0x01, 0x49, 0x13, 0xb7, 0x30, 0xee, 0x20,
|
||||
0xf8, 0x83, 0x5a, 0x22, 0x2e, 0x22, 0x75, 0x13, 0x09, 0x8a, 0x88, 0xbd,
|
||||
0x2e, 0x23, 0x6a, 0x0b, 0x09, 0x62, 0x2f, 0x11, 0x84, 0x88, 0x25, 0x23,
|
||||
0xc4, 0x56, 0x17, 0x11, 0x37, 0x30, 0xe3, 0x22, 0x12, 0x37, 0x50, 0x21,
|
||||
0x21, 0xf8, 0xc3, 0x5e, 0x57, 0x50, 0x57, 0x90, 0xd7, 0xeb, 0xfd, 0xfe,
|
||||
0x7c, 0x3f, 0xcf, 0xe7, 0xfb, 0xfb, 0x7c, 0x7e, 0xcf, 0xf9, 0xfc, 0xce,
|
||||
0xef, 0xf9, 0x3d, 0xcf, 0x73, 0xb6, 0x99, 0x79, 0x7e, 0xbf, 0x39, 0xcb,
|
||||
0x73, 0x9e, 0xf3, 0x9c, 0xe7, 0x9c, 0xf3, 0x3b, 0x33, 0x73, 0xce, 0x79,
|
||||
0xa6, 0x33, 0x6f, 0x0c, 0x60, 0x12, 0x00, 0x21, 0x08, 0xc3, 0x40, 0x00,
|
||||
0xdc, 0x83, 0x4a, 0x6b, 0x09, 0x0e, 0x2f, 0x03, 0x04, 0x00, 0x7a, 0x65,
|
||||
0x73, 0x6b, 0x4b, 0xcb, 0xf5, 0x21, 0x07, 0xd1, 0x97, 0x11, 0x9c, 0x14,
|
||||
0x1c, 0x84, 0xc2, 0x09, 0x08, 0x89, 0x06, 0x82, 0x06, 0x12, 0x0d, 0x04,
|
||||
0x0d, 0x24, 0x1a, 0x08, 0x1a, 0x48, 0x34, 0x10, 0x34, 0x90, 0x68, 0x20,
|
||||
0x68, 0x20, 0xd1, 0x40, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
|
||||
0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0x10, 0x12, 0x71, 0x69,
|
||||
0x9b, 0x9a, 0xcb, 0x5a, 0x9b, 0x8e, 0xcd, 0xa6, 0xd5, 0xd6, 0x89, 0xcd,
|
||||
0x60, 0x6e, 0x64, 0xac, 0x89, 0xb1, 0x8c, 0x01, 0x11, 0x21, 0x06, 0xbc,
|
||||
0xb4, 0xd7, 0xfa, 0x8f, 0xc5, 0x53, 0xfd, 0x55, 0xb3, 0x71, 0xce, 0x6c,
|
||||
0x9a, 0x2c, 0x3c, 0x80, 0x69, 0xb6, 0x02, 0x67, 0x3c, 0xed, 0xdc, 0x45,
|
||||
0x63, 0x63, 0x2f, 0xe3, 0xe7, 0xfc, 0xb5, 0x9d, 0x27, 0x59, 0xa4, 0x17,
|
||||
0x10, 0x62, 0x80, 0x21, 0xc4, 0x00, 0x43, 0x88, 0x01, 0x86, 0x10, 0x03,
|
||||
0x0c, 0x21, 0x06, 0x18, 0x42, 0x9f, 0x66, 0x93, 0xcc, 0xbd, 0xee, 0x66,
|
||||
0x66, 0x32, 0x73, 0xf4, 0x7a, 0x33, 0xa9, 0xfa, 0x31, 0xa3, 0x51, 0x8e,
|
||||
0x1e, 0x0d, 0x60, 0x47, 0x78, 0x75, 0x7a, 0xb9, 0x2b, 0x4e, 0x57, 0x8c,
|
||||
0xaa, 0x00, 0x1a, 0xed, 0x01, 0x54, 0x55, 0x00, 0xf9, 0x0b, 0x39, 0xf5,
|
||||
0x97, 0xff, 0xfe, 0x0b, 0x13, 0xa0, 0x0a, 0xa0, 0x0a, 0xa0, 0x0a, 0xa0,
|
||||
0x0a, 0xa0, 0x5e, 0x49, 0x78, 0x4f, 0x07, 0xdf, 0x09, 0x0f, 0x78, 0x0f,
|
||||
0x78, 0x8f, 0x1a, 0x7e, 0xe3, 0xed, 0x5c, 0xef, 0xbe, 0xec, 0xe5, 0x6e,
|
||||
0xe7, 0x0a, 0x0a, 0xc8, 0x3b, 0xb2, 0x13, 0x50, 0x05, 0x54, 0x01, 0x2d,
|
||||
0x14, 0x14, 0x90, 0x7e, 0x94, 0x9f, 0xfc, 0xbd, 0xae, 0xce, 0x8d, 0x1f,
|
||||
0xab, 0x3a, 0xb2, 0x1b, 0xaa, 0xa4, 0x2a, 0xa9, 0x4a, 0xd2, 0x2b, 0x71,
|
||||
0x88, 0x9b, 0x9d, 0x74, 0xf0, 0x13, 0xbb, 0x2a, 0xfd, 0xf5, 0x42, 0xba,
|
||||
0x4a, 0xc2, 0xed, 0x38, 0x79, 0x22, 0xb7, 0xf3, 0x08, 0x15, 0x07, 0x14,
|
||||
0x05, 0x50, 0x14, 0x40, 0x51, 0x00, 0x45, 0x01, 0x14, 0x05, 0xfa, 0x47,
|
||||
0xec, 0xbe, 0x43, 0x80, 0x82, 0x84, 0x08, 0x20, 0x02, 0x48, 0x21, 0xa2,
|
||||
0x52, 0xa4, 0x50, 0x35, 0x5f, 0xaa, 0xb7, 0xf8, 0x10, 0x7a, 0xa2, 0x56,
|
||||
0x97, 0x9f, 0x86, 0xde, 0x74, 0xbf, 0xb4, 0x33, 0xfa, 0x76, 0x3f, 0x4a,
|
||||
0x35, 0x84, 0xb0, 0xd9, 0x05, 0xdd, 0x99, 0x3c, 0x94, 0xba, 0x4c, 0x5b,
|
||||
0xe8, 0x42, 0xee, 0x9d, 0x82, 0x5e, 0xfc, 0xb3, 0xfe, 0x2d, 0x39, 0xfd,
|
||||
0x9b, 0x3c, 0x94, 0xaa, 0x5a, 0x90, 0xca, 0x64, 0x5e, 0x24, 0x21, 0x50,
|
||||
0xa5, 0xea, 0x43, 0x21, 0x84, 0x10, 0x98, 0xbc, 0xfa, 0x2b, 0x97, 0x3a,
|
||||
0x27, 0xb4, 0x4b, 0x08, 0xd0, 0x56, 0xa7, 0x9a, 0xdc, 0xdc, 0xf3, 0xfd,
|
||||
0x80, 0xd0, 0x4e, 0x8f, 0xd0, 0x39, 0x21, 0xe1, 0x55, 0x1d, 0x1d, 0xbd,
|
||||
0x82, 0x48, 0x4e, 0xf2, 0xc5, 0x65, 0x79, 0xac, 0x83, 0xa7, 0x96, 0x8e,
|
||||
0xc5, 0xd1, 0x51, 0x09, 0x9b, 0x5d, 0x20, 0x0d, 0x48, 0x5b, 0xe8, 0xc2,
|
||||
0x27, 0x1e, 0x16, 0x48, 0x3f, 0xed, 0xa7, 0x2f, 0xef, 0xc1, 0x3d, 0x16,
|
||||
0xd2, 0x02, 0xaf, 0xea, 0xe8, 0xe8, 0x84, 0xa8, 0x24, 0x1f, 0x93, 0x57,
|
||||
0xca, 0xcf, 0x5b, 0xb1, 0x07, 0x63, 0x87, 0xc7, 0xa3, 0xd7, 0x28, 0xb4,
|
||||
0xe9, 0x95, 0xa0, 0xad, 0x28, 0x8c, 0xe7, 0x16, 0xbb, 0x27, 0x76, 0xe9,
|
||||
0x95, 0x40, 0x24, 0xa2, 0x52, 0x52, 0xa6, 0x50, 0x35, 0x5f, 0x61, 0xd5,
|
||||
0x47, 0xe5, 0x65, 0xfd, 0xc9, 0x5e, 0xea, 0xcb, 0xe0, 0x0b, 0x35, 0xbc,
|
||||
0x82, 0xb6, 0xbb, 0xc1, 0x42, 0x40, 0x90, 0x56, 0xe8, 0xc6, 0x9f, 0xce,
|
||||
0xff, 0x6a, 0x2f, 0xc6, 0x99, 0x9c, 0x78, 0x05, 0x91, 0xc4, 0x9b, 0x16,
|
||||
0x0a, 0x96, 0x44, 0xf2, 0x21, 0x38, 0xd1, 0xda, 0x2f, 0x2d, 0x65, 0x28,
|
||||
0x84, 0xb6, 0x69, 0x68, 0x95, 0xe0, 0xfa, 0x01, 0xbe, 0xe8, 0xea, 0x41,
|
||||
0x09, 0xe1, 0x21, 0x1c, 0x0d, 0xbd, 0xaa, 0xa3, 0xd0, 0x6b, 0x9e, 0xda,
|
||||
0x32, 0xf7, 0x7f, 0xfb, 0x3f, 0x0f, 0x07, 0x4f, 0x27, 0xa0, 0xed, 0x6e,
|
||||
0x90, 0x06, 0xa4, 0x15, 0xba, 0xe1, 0x3d, 0x0b, 0xc8, 0xbf, 0x5d, 0xfc,
|
||||
0x24, 0xb7, 0x23, 0xf4, 0x9e, 0x0e, 0x9e, 0x34, 0xb1, 0xea, 0x2b, 0x4e,
|
||||
0x6e, 0x3c, 0xe0, 0x44, 0xb3, 0xa2, 0xac, 0x38, 0xa1, 0x6d, 0x27, 0x04,
|
||||
0xad, 0x2a, 0xc2, 0x4a, 0xcb, 0x1e, 0xd6, 0x49, 0x05, 0xa8, 0x10, 0x42,
|
||||
0x98, 0x52, 0xb4, 0x22, 0xdc, 0x57, 0x3d, 0xdc, 0x7e, 0x61, 0x47, 0x4c,
|
||||
0x5e, 0x8c, 0x4e, 0x72, 0x02, 0xda, 0x01, 0x48, 0xc1, 0x41, 0xd8, 0x15,
|
||||
0x7b, 0x04, 0x6d, 0x00, 0x48, 0x2a, 0xc6, 0x70, 0x7b, 0xcd, 0x9f, 0xe3,
|
||||
0x9b, 0xf3, 0xd5, 0x24, 0x30, 0x38, 0x49, 0x09, 0x54, 0xa9, 0xfa, 0xd4,
|
||||
0x3d, 0x9a, 0xab, 0x20, 0xb8, 0x2a, 0xca, 0x2a, 0x6d, 0xd0, 0x5e, 0xda,
|
||||
0xa8, 0x42, 0x54, 0x83, 0x7b, 0xfe, 0xe2, 0x79, 0x54, 0x01, 0xaa, 0x34,
|
||||
0xf4, 0x55, 0xd6, 0xa8, 0x8e, 0xf6, 0x3f, 0xc8, 0x82, 0x83, 0xd0, 0x57,
|
||||
0xe9, 0x50, 0xa5, 0x10, 0x76, 0x02, 0xa4, 0xbd, 0xe8, 0x0a, 0x69, 0x03,
|
||||
0x80, 0xaf, 0xd2, 0xa1, 0x4a, 0x27, 0xd3, 0xf6, 0x00, 0x77, 0xef, 0xab,
|
||||
0x70, 0xa8, 0x52, 0x08, 0x54, 0x2a, 0x85, 0xdb, 0xf1, 0xcd, 0xf3, 0x72,
|
||||
0xc2, 0x8a, 0x93, 0x28, 0xb4, 0xd3, 0x09, 0xed, 0x47, 0x1b, 0xd1, 0x49,
|
||||
0xac, 0x14, 0xd2, 0x39, 0x87, 0x28, 0xac, 0x10, 0x92, 0x30, 0x25, 0xdd,
|
||||
0x70, 0xfb, 0x57, 0x25, 0x27, 0x20, 0x92, 0xa7, 0x21, 0x54, 0xc7, 0x44,
|
||||
0xb1, 0x6a, 0x14, 0x5a, 0xed, 0x9d, 0x6e, 0x20, 0x97, 0x4a, 0x0b, 0x6c,
|
||||
0xf6, 0x8d, 0x6a, 0x2d, 0x3d, 0x63, 0xa5, 0x66, 0xb6, 0x52, 0x27, 0x54,
|
||||
0xd3, 0x78, 0x65, 0x3f, 0x52, 0xa5, 0x9a, 0x0a, 0x79, 0x86, 0x88, 0xae,
|
||||
0x81, 0x5a, 0xa4, 0x2d, 0x74, 0x21, 0xa9, 0x18, 0x4b, 0x2a, 0x01, 0xec,
|
||||
0x57, 0x9e, 0x82, 0x8f, 0xe1, 0x14, 0x68, 0xaa, 0xa8, 0x9d, 0x9d, 0xbe,
|
||||
0xaf, 0x10, 0xc2, 0x23, 0x4c, 0x82, 0x5a, 0x59, 0x7b, 0xf7, 0x99, 0x6a,
|
||||
0xee, 0x93, 0xbc, 0x4e, 0xad, 0x56, 0xab, 0x49, 0x70, 0xd9, 0xd5, 0x20,
|
||||
0x20, 0x6d, 0x29, 0x80, 0xf7, 0x4a, 0xec, 0xfd, 0xd9, 0x1d, 0x04, 0x7a,
|
||||
0x1a, 0xce, 0x3c, 0x47, 0x3c, 0x64, 0xf0, 0xcc, 0x01, 0x4e, 0xbc, 0x87,
|
||||
0x83, 0x9f, 0xcb, 0x07, 0xd5, 0x81, 0xc4, 0x1d, 0xe7, 0x1c, 0xa1, 0x26,
|
||||
0x21, 0x8f, 0x9c, 0xd7, 0x3e, 0xac, 0x86, 0x50, 0x0b, 0x0c, 0xc3, 0x39,
|
||||
0xe4, 0x80, 0x1c, 0x58, 0x23, 0x02, 0xed, 0x8b, 0x2e, 0x78, 0x0f, 0x07,
|
||||
0x4f, 0x27, 0x20, 0xaa, 0x51, 0x6f, 0x0f, 0xb3, 0x47, 0x4f, 0x9a, 0x8a,
|
||||
0x5d, 0x2c, 0x3f, 0x12, 0x9d, 0x10, 0xb1, 0x59, 0x8b, 0x94, 0x88, 0x6b,
|
||||
0xba, 0xec, 0x9a, 0x65, 0x33, 0x6b, 0x36, 0x9b, 0x52, 0x53, 0xa8, 0xb1,
|
||||
0x59, 0xd2, 0x41, 0x68, 0x33, 0xe6, 0x10, 0x69, 0xe2, 0x37, 0x05, 0x17,
|
||||
0x01, 0x51, 0xf5, 0x61, 0xe4, 0xeb, 0x9e, 0x86, 0x54, 0x61, 0x70, 0x10,
|
||||
0xa6, 0xd2, 0x9b, 0x16, 0xd5, 0x7b, 0x4a, 0x51, 0x41, 0xc3, 0x68, 0x26,
|
||||
0xff, 0x2e, 0x15, 0xa1, 0x99, 0xdf, 0xe1, 0xa6, 0x43, 0x85, 0x50, 0xab,
|
||||
0x08, 0x84, 0xaa, 0x08, 0xc3, 0x69, 0xb5, 0xdf, 0x55, 0xe6, 0x2c, 0x54,
|
||||
0x0e, 0xb8, 0x0a, 0x20, 0x74, 0x02, 0xda, 0xd5, 0x85, 0x94, 0xd5, 0x58,
|
||||
0x50, 0x09, 0x60, 0x1e, 0xdc, 0xa9, 0x3e, 0x39, 0x25, 0x91, 0xbc, 0x12,
|
||||
0xd5, 0xfb, 0x56, 0x35, 0xd5, 0x82, 0x93, 0x2a, 0xc9, 0x57, 0x45, 0x95,
|
||||
0x87, 0xb3, 0xb2, 0xa8, 0x35, 0x9a, 0x42, 0x34, 0x85, 0x25, 0xa9, 0x51,
|
||||
0x24, 0x50, 0x84, 0x36, 0x13, 0x40, 0xa2, 0x49, 0x90, 0xfb, 0x4a, 0x4a,
|
||||
0x02, 0xa7, 0xee, 0x6a, 0xae, 0x72, 0x8f, 0x9e, 0x85, 0x80, 0xf0, 0x89,
|
||||
0x0e, 0x1a, 0x12, 0x82, 0xd7, 0xc1, 0x4c, 0x0d, 0x01, 0xc5, 0x2c, 0x34,
|
||||
0xe7, 0xae, 0xdf, 0x15, 0x5c, 0x08, 0x8e, 0xd5, 0x40, 0x30, 0x06, 0x84,
|
||||
0x40, 0x09, 0x70, 0x74, 0x02, 0xda, 0xd5, 0x05, 0x9f, 0xe0, 0xa0, 0x54,
|
||||
0x02, 0xf0, 0x9e, 0x17, 0x2f, 0xe0, 0x59, 0x08, 0x11, 0x5d, 0xc3, 0x96,
|
||||
0x42, 0xd9, 0x95, 0xbc, 0x32, 0x3a, 0xa9, 0x38, 0x15, 0x06, 0x61, 0x59,
|
||||
0x4e, 0x47, 0x47, 0xe9, 0x0a, 0x11, 0x07, 0x14, 0x14, 0x50, 0x68, 0xb3,
|
||||
0xa2, 0x8c, 0x42, 0x20, 0xd2, 0x5d, 0xdc, 0xa5, 0x06, 0x27, 0x11, 0x59,
|
||||
0x4f, 0xe9, 0x9a, 0x56, 0xab, 0xb2, 0x74, 0x10, 0xa6, 0x9c, 0x2d, 0xf8,
|
||||
0x2a, 0x80, 0xd0, 0x39, 0x01, 0x27, 0x20, 0x02, 0x14, 0xa1, 0x08, 0x45,
|
||||
0x28, 0x42, 0x11, 0x8a, 0x50, 0x84, 0x22, 0x14, 0xa1, 0x08, 0x45, 0x28,
|
||||
0x42, 0x11, 0x8a, 0x30, 0xe5, 0x6c, 0x41, 0x29, 0x04, 0x90, 0xb2, 0x9b,
|
||||
0x66, 0x2b, 0xf0, 0x2a, 0xc2, 0x12, 0x3d, 0x81, 0x4a, 0x57, 0x55, 0x02,
|
||||
0x09, 0x61, 0xa2, 0x82, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
|
||||
0x92, 0x24, 0x49, 0x92, 0x09, 0x65, 0x12, 0x02, 0x09, 0x82, 0xef, 0xa5,
|
||||
0xe1, 0x3a, 0xbf, 0x5e, 0x3a, 0x24, 0x2a, 0x01, 0xf8, 0x44, 0x87, 0x14,
|
||||
0x28, 0x9d, 0x03, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
|
||||
0x49, 0x92, 0x24, 0x7d, 0x12, 0xc7, 0x44, 0x25, 0x00, 0x9f, 0x58, 0xe3,
|
||||
0x57, 0x48, 0xa3, 0xaf, 0x75, 0x39, 0x44, 0x21, 0x10, 0x9d, 0x44, 0x28,
|
||||
0x48, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
|
||||
0x19, 0x95, 0x51, 0x08, 0x44, 0x22, 0xff, 0x54, 0x42, 0x08, 0xdb, 0x53,
|
||||
0x0c, 0xe6, 0x4a, 0x2a, 0x01, 0xa4, 0x2c, 0x46, 0xa7, 0x34, 0x87, 0x7e,
|
||||
0x70, 0xf2, 0xc1, 0xf5, 0x9d, 0xc8, 0x3b, 0xe9, 0x0b, 0xe5, 0x85, 0x7d,
|
||||
0x42, 0x9e, 0xe8, 0x13, 0xf2, 0x44, 0x9f, 0x90, 0x27, 0xfa, 0x84, 0x3c,
|
||||
0xd1, 0x27, 0xe4, 0x89, 0x3e, 0x91, 0xb2, 0x18, 0x33, 0x95, 0x00, 0x52,
|
||||
0x66, 0x89, 0xcb, 0x97, 0x29, 0x01, 0x3c, 0xc2, 0xe4, 0x84, 0x50, 0x94,
|
||||
0x1e, 0x10, 0x12, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10,
|
||||
0x04, 0x41, 0x78, 0x08, 0x9f, 0xbc, 0x32, 0x41, 0xec, 0x59, 0x49, 0xe0,
|
||||
0xc2, 0xd3, 0x21, 0x69, 0x38, 0x79, 0x28, 0xbd, 0xa7, 0x43, 0x22, 0xd0,
|
||||
0xb9, 0xe4, 0x01, 0x25, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10,
|
||||
0x04, 0x41, 0x78, 0x4f, 0x87, 0xa4, 0x5d, 0x0b, 0xbc, 0xa2, 0x81, 0x5f,
|
||||
0x99, 0x4a, 0x20, 0x9c, 0x58, 0xe9, 0x62, 0xf2, 0xca, 0x28, 0x8c, 0x4a,
|
||||
0x21, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10,
|
||||
0x44, 0x14, 0x46, 0x21, 0x10, 0x89, 0xfc, 0x32, 0x85, 0x92, 0xb2, 0xbd,
|
||||
0x9b, 0xd2, 0x5c, 0xa6, 0x05, 0x29, 0x8b, 0x31, 0x2b, 0xd0, 0x0a, 0x80,
|
||||
0xfa, 0x00, 0x54, 0x71, 0x02, 0xda, 0x06, 0x34, 0x08, 0xa0, 0xef, 0x04,
|
||||
0x44, 0xca, 0xce, 0x24, 0x53, 0x08, 0x20, 0x65, 0xa9, 0xf9, 0xe9, 0xc2,
|
||||
0x09, 0x91, 0x5f, 0x5f, 0x51, 0x98, 0x68, 0x12, 0x44, 0xa2, 0x15, 0xad,
|
||||
0x9c, 0x10, 0x09, 0x22, 0x59, 0x12, 0x00, 0xdf, 0x2d, 0x24, 0xb0, 0x8e,
|
||||
0x1e, 0x9f, 0x0e, 0x89, 0x34, 0xf0, 0x89, 0x0e, 0x89, 0xb4, 0x02, 0x40,
|
||||
0x00, 0xa4, 0x15, 0x00, 0x02, 0xa0, 0x10, 0x80, 0x4f, 0x74, 0x48, 0xb4,
|
||||
0xc0, 0x27, 0xac, 0xf0, 0x3d, 0x14, 0x02, 0xfa, 0x51, 0xa7, 0x8c, 0x34,
|
||||
0x91, 0x88, 0xb4, 0x52, 0xda, 0x2d, 0x04, 0xa2, 0x32, 0x2a, 0x81, 0xc8,
|
||||
0x6c, 0x19, 0xae, 0x51, 0x28, 0x94, 0x07, 0xd1, 0xab, 0x6a, 0x91, 0x13,
|
||||
0x97, 0x49, 0x83, 0x94, 0xc5, 0x98, 0x49, 0x2b, 0x00, 0x04, 0x40, 0x27,
|
||||
0xa0, 0x6d, 0x80, 0x00, 0xe8, 0x04, 0x44, 0xca, 0xce, 0x24, 0x53, 0x08,
|
||||
0x20, 0x65, 0x59, 0xba, 0xd3, 0x3f, 0x53, 0x65, 0x42, 0xc0, 0x5d, 0xed,
|
||||
0x85, 0x8b, 0xc9, 0x09, 0x91, 0x20, 0x12, 0xad, 0x68, 0x25, 0x04, 0x12,
|
||||
0x44, 0xb2, 0x24, 0xc0, 0xeb, 0x85, 0x44, 0xc3, 0x01, 0xe9, 0xa1, 0xf7,
|
||||
0x98, 0x28, 0x04, 0xe0, 0x13, 0x1d, 0x12, 0x69, 0x05, 0x80, 0x00, 0x48,
|
||||
0x2b, 0x00, 0x04, 0x40, 0x21, 0x00, 0x9f, 0xe8, 0x90, 0x68, 0xc1, 0x2c,
|
||||
0xe1, 0xf0, 0xa1, 0x12, 0x69, 0x8a, 0x6f, 0x0e, 0x1a, 0x63, 0x21, 0x2c,
|
||||
0x0a, 0x89, 0xf6, 0x28, 0xed, 0x16, 0x02, 0x51, 0x19, 0x95, 0x40, 0x74,
|
||||
0x47, 0x76, 0xa2, 0x51, 0x29, 0x09, 0x67, 0xe1, 0x0c, 0x1e, 0xf1, 0x9a,
|
||||
0x99, 0x16, 0x24, 0x97, 0x2d, 0x64, 0x89, 0x06, 0xaa, 0xe7, 0x00, 0x27,
|
||||
0xba, 0x5b, 0x08, 0x6b, 0x09, 0x12, 0xd4, 0x83, 0x04, 0xf5, 0xa0, 0x2b,
|
||||
0x48, 0x2e, 0x98, 0xcb, 0xcc, 0x01, 0x4e, 0x8e, 0x83, 0xbd, 0xce, 0x69,
|
||||
0x08, 0x59, 0xc1, 0x92, 0xe0, 0x7d, 0x26, 0x9a, 0x04, 0x91, 0x84, 0x00,
|
||||
0x8d, 0xd0, 0x3a, 0x41, 0x24, 0x4b, 0xba, 0x1f, 0x21, 0xd1, 0xd0, 0x27,
|
||||
0xfe, 0x6e, 0x67, 0x7f, 0x44, 0xa4, 0x81, 0xf7, 0x74, 0x48, 0x14, 0x02,
|
||||
0x20, 0x0d, 0x28, 0x84, 0x35, 0x41, 0x10, 0x04, 0x41, 0x78, 0x55, 0x47,
|
||||
0x4f, 0x0b, 0x96, 0xd5, 0x9f, 0x3b, 0xcf, 0x2d, 0x28, 0x95, 0x40, 0x4c,
|
||||
0x7e, 0xfb, 0x9a, 0x2c, 0x85, 0x32, 0xc6, 0x42, 0xa8, 0x04, 0x84, 0xd6,
|
||||
0x85, 0x32, 0x2a, 0x81, 0xfc, 0x09, 0xab, 0x44, 0xa1, 0x14, 0xb1, 0x48,
|
||||
0xd9, 0x9d, 0x8b, 0xdb, 0xee, 0xe0, 0xc4, 0xb9, 0x1b, 0xa4, 0x40, 0x43,
|
||||
0x66, 0x0e, 0x70, 0x42, 0x25, 0x00, 0x0a, 0x61, 0x4d, 0x10, 0x04, 0x41,
|
||||
0x10, 0x29, 0x88, 0x31, 0x53, 0xb8, 0x41, 0xe7, 0x6c, 0x2f, 0xc7, 0x1c,
|
||||
0x0d, 0x41, 0x52, 0x02, 0x09, 0x65, 0xfa, 0xe4, 0xe0, 0x24, 0x01, 0x24,
|
||||
0x21, 0x40, 0x23, 0xb4, 0x4e, 0x10, 0x09, 0x58, 0x5a, 0xb6, 0xfc, 0x10,
|
||||
0x09, 0x20, 0x09, 0x09, 0xf8, 0x44, 0x87, 0x74, 0x72, 0x4e, 0x17, 0x71,
|
||||
0x22, 0xf4, 0x89, 0x0e, 0x89, 0x42, 0x00, 0xa4, 0x01, 0x85, 0xb0, 0x26,
|
||||
0x08, 0x82, 0x20, 0x08, 0x9f, 0xe8, 0x90, 0x12, 0x90, 0x6f, 0xbe, 0xfe,
|
||||
0xf4, 0x2d, 0xf8, 0x04, 0x87, 0x44, 0x21, 0x10, 0x73, 0x88, 0xc3, 0xf2,
|
||||
0x0a, 0xeb, 0x37, 0xcf, 0xe8, 0x24, 0x0a, 0x01, 0x27, 0x84, 0xd0, 0x3a,
|
||||
0x3a, 0x89, 0xf2, 0xe4, 0xd9, 0x8c, 0x5c, 0xe9, 0x59, 0x46, 0x61, 0x74,
|
||||
0x22, 0x39, 0x49, 0x41, 0x8d, 0x99, 0xca, 0x1f, 0xef, 0x79, 0x97, 0xc9,
|
||||
0xd1, 0x10, 0x18, 0x1c, 0x84, 0xcc, 0x01, 0x4e, 0xe8, 0x04, 0xb4, 0x3f,
|
||||
0x41, 0x10, 0x04, 0x41, 0xa4, 0x10, 0xcc, 0xe5, 0xf5, 0xca, 0x56, 0x1e,
|
||||
0xbc, 0xf7, 0xb5, 0x93, 0x94, 0x9d, 0x49, 0x56, 0xb0, 0x24, 0x84, 0x89,
|
||||
0xf8, 0xf3, 0x66, 0xef, 0x23, 0x41, 0x24, 0x27, 0x04, 0x8d, 0xd0, 0x3a,
|
||||
0x41, 0xa4, 0xe5, 0xfb, 0xdd, 0x63, 0x12, 0x40, 0xa2, 0xa1, 0x4f, 0x74,
|
||||
0x48, 0x24, 0x1c, 0x16, 0xbb, 0xfd, 0xf9, 0xd7, 0xf3, 0x2e, 0x3c, 0x85,
|
||||
0x00, 0x48, 0x03, 0x0a, 0x61, 0x4d, 0x10, 0x04, 0x41, 0x10, 0x3e, 0x31,
|
||||
0xaf, 0x1f, 0xf8, 0xe8, 0x63, 0xec, 0x0f, 0xef, 0xd0, 0xc0, 0x7b, 0x38,
|
||||
0x78, 0xd2, 0xc4, 0xe4, 0xa3, 0xe5, 0x89, 0xbf, 0x21, 0x68, 0x51, 0x08,
|
||||
0xa1, 0x04, 0x94, 0xd6, 0x51, 0xec, 0x23, 0xb8, 0x94, 0x6d, 0x21, 0x50,
|
||||
0x14, 0x12, 0x85, 0x42, 0x99, 0xb2, 0x33, 0xc9, 0x14, 0x02, 0xf8, 0x74,
|
||||
0x5e, 0xdf, 0xb8, 0xc0, 0xac, 0x3f, 0xf9, 0x71, 0x07, 0xff, 0x67, 0x31,
|
||||
0xe6, 0x98, 0x61, 0xc8, 0x31, 0xc3, 0x90, 0x63, 0x86, 0x21, 0xc7, 0x0c,
|
||||
0x43, 0x8e, 0x19, 0x86, 0x1c, 0x33, 0x0c, 0x39, 0x66, 0x18, 0x72, 0xcc,
|
||||
0x88, 0xc8, 0xf9, 0xd1, 0x1b, 0xe1, 0x81, 0xb6, 0xc3, 0x8e, 0xe6, 0x4b,
|
||||
0x0a, 0x01, 0xa4, 0x4c, 0x43, 0x96, 0x94, 0x40, 0x42, 0x99, 0x84, 0x00,
|
||||
0x31, 0xd5, 0x88, 0xef, 0x65, 0x68, 0xe9, 0x18, 0xf0, 0x09, 0x40, 0x3d,
|
||||
0x00, 0x15, 0x25, 0x15, 0x25, 0x15, 0x25, 0x15, 0x25, 0x15, 0x25, 0x15,
|
||||
0x65, 0xba, 0x97, 0xcd, 0x97, 0x39, 0xe8, 0x84, 0x34, 0x0a, 0x20, 0x4e,
|
||||
0x48, 0x78, 0x47, 0x07, 0x47, 0xaf, 0x20, 0x48, 0x83, 0xd3, 0xfb, 0xfe,
|
||||
0xe9, 0x22, 0x0f, 0x21, 0xce, 0xa1, 0x53, 0xa0, 0x08, 0x29, 0x42, 0x8a,
|
||||
0x90, 0x22, 0xa4, 0x08, 0x29, 0x42, 0x6e, 0x24, 0x59, 0x76, 0x39, 0xf8,
|
||||
0x86, 0x67, 0xa1, 0x8a, 0x57, 0x10, 0x14, 0x02, 0xf0, 0x0a, 0x07, 0xa1,
|
||||
0x57, 0x22, 0x96, 0x2e, 0x96, 0x4e, 0x28, 0x04, 0xee, 0x89, 0x97, 0x75,
|
||||
0x82, 0x31, 0x3a, 0x89, 0x91, 0x88, 0x11, 0x88, 0x11, 0x88, 0x11, 0x88,
|
||||
0x11, 0x88, 0x11, 0x88, 0xee, 0xc4, 0xf5, 0xe1, 0xfd, 0x9d, 0xc7, 0x85,
|
||||
0x57, 0x42, 0x09, 0x44, 0xa5, 0x38, 0x91, 0x94, 0x29, 0x27, 0xf3, 0x39,
|
||||
0x66, 0x35, 0xe6, 0x98, 0x61, 0xc8, 0x31, 0xe3, 0x1c, 0x6e, 0xbb, 0xd3,
|
||||
0xe4, 0xc9, 0x0b, 0xa7, 0x71, 0x03, 0xf9, 0x8f, 0x0c, 0x43, 0x8e, 0x19,
|
||||
0x86, 0x1c, 0x33, 0x0c, 0x39, 0x66, 0x18, 0x72, 0xcc, 0x30, 0xe4, 0x45,
|
||||
0xc6, 0xb2, 0xff, 0xdb, 0xbf, 0xf9, 0x5b, 0x80, 0x21, 0x47, 0x07, 0x43,
|
||||
0x88, 0x02, 0x83, 0x8b, 0xa4, 0x41, 0x14, 0x9c, 0x10, 0x25, 0x39, 0xa4,
|
||||
0x40, 0x70, 0x3e, 0x20, 0x54, 0x07, 0x40, 0xb1, 0x2b, 0xba, 0xc7, 0x4b,
|
||||
0x23, 0x42, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0xc9, 0x4f,
|
||||
0x22, 0x7e, 0xec, 0xc2, 0x95, 0x04, 0x0a, 0x42, 0x0a, 0x42, 0x0a, 0x42,
|
||||
0x0a, 0x42, 0x2a, 0x09, 0x78, 0x51, 0x47, 0xe9, 0x86, 0x02, 0xaa, 0x80,
|
||||
0x2a, 0xa0, 0x85, 0x82, 0x02, 0x76, 0x56, 0x1f, 0xfc, 0xf3, 0xe3, 0xde,
|
||||
0xd9, 0x7e, 0xba, 0xe2, 0x16, 0x59, 0x43, 0x9f, 0x2b, 0x56, 0xd0, 0x95,
|
||||
0xe2, 0x2e, 0xb4, 0x67, 0x57, 0x7d, 0xa4, 0xbb, 0x8f, 0x73, 0x96, 0xc5,
|
||||
0x55, 0x09, 0x0e, 0xec, 0x8a, 0x2a, 0xa9, 0x4a, 0xaa, 0x92, 0xaa, 0x24,
|
||||
0x85, 0x40, 0xe1, 0x35, 0x8b, 0x30, 0x08, 0xe0, 0x48, 0x88, 0x00, 0x22,
|
||||
0xb8, 0xec, 0x7f, 0xff, 0xb1, 0x5f, 0xba, 0x68, 0x2e, 0x29, 0x59, 0x10,
|
||||
0xd9, 0x32, 0x5c, 0x72, 0xe7, 0xa4, 0x1a, 0x17, 0x13, 0xff, 0xeb, 0x77,
|
||||
0x3e, 0xe9, 0x96, 0x02, 0x44, 0x00, 0x11, 0x40, 0x04, 0x10, 0x01, 0x44,
|
||||
0x00, 0x71, 0x22, 0x92, 0xef, 0xd3, 0x40, 0x28, 0x01, 0x48, 0x34, 0x10,
|
||||
0x34, 0x90, 0x68, 0x20, 0x68, 0x20, 0xd1, 0x40, 0xd0, 0x40, 0xa2, 0x81,
|
||||
0xa0, 0x81, 0x44, 0x03, 0x41, 0x03, 0x89, 0x06, 0x82, 0x06, 0x12, 0x0d,
|
||||
0x04, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x01, 0xf9, 0xd5, 0xa7, 0xe1, 0xfc, 0x9a,
|
||||
0xed, 0xe9, 0xd0, 0xbb, 0xf0, 0xac, 0xf4, 0x35, 0xd5, 0x5a, 0x87, 0xdc,
|
||||
0x52, 0xeb, 0xc0, 0x3f, 0x4b, 0xf9, 0x28, 0xef, 0xad, 0x9e, 0xd5, 0x8a,
|
||||
0x91, 0xd1, 0x84, 0x7b, 0x13, 0x77, 0x0e, 0x2d, 0xc7, 0x25, 0xb5, 0xa6,
|
||||
0xa5, 0x56, 0xe3, 0x08, 0x4d, 0x4b, 0xad, 0x46, 0x70, 0xe7, 0x2d, 0x6d,
|
||||
0x9e, 0xa5, 0x6c, 0x37, 0x8b, 0x6a, 0xe0, 0x74, 0x59, 0x78, 0x8a, 0x1a,
|
||||
0x83, 0x4c, 0x3d, 0x1d, 0xfd, 0x7f, 0xf4, 0xee, 0x77, 0xbd, 0xdb, 0x5d,
|
||||
0x89, 0xb1, 0x74, 0xe6, 0x77, 0xa5, 0xf7, 0x0a, 0x3d, 0x83, 0x2a, 0x7a,
|
||||
0xe8, 0xe9, 0x96, 0xf4, 0xd0, 0xdd, 0xbd, 0x44, 0xbb, 0xe4, 0xd6, 0xff,
|
||||
0xd5, 0xfc, 0xdb, 0x58, 0xcc, 0x37, 0xe7, 0xf9, 0xf0, 0x49, 0x2e, 0x66,
|
||||
0x7f, 0xf5, 0x17, 0xee, 0x7d, 0x86, 0x31, 0x3c, 0xbc, 0x18, 0x1e, 0x8e,
|
||||
0xc3, 0xc3, 0xbb, 0xc3, 0xc3, 0x1f, 0x0e, 0xff, 0xcc, 0xb3, 0xfe, 0x0f,
|
||||
0x6d, 0xb0, 0x1a, 0x3b, 0xbc, 0x18, 0x1e, 0xfe, 0x79, 0x78, 0xcd, 0xab,
|
||||
0x8b, 0x5f, 0x43, 0xbb, 0x35, 0x6e, 0x67, 0x61, 0x53, 0x63, 0xdb, 0xfc,
|
||||
0x65, 0x2e, 0x7d, 0xc6, 0xab, 0x67, 0xa7, 0x55, 0xdb, 0x43, 0xe1, 0x56,
|
||||
0xa7, 0x74, 0xc7, 0x23, 0x13, 0x28, 0x44, 0xf5, 0xbf, 0x69, 0x6e, 0xfd,
|
||||
0x34, 0x07, 0xde, 0xfb, 0xf1, 0x5b, 0x06, 0xe7, 0xcb, 0xea, 0xa4, 0x53,
|
||||
0xee, 0x0e, 0xab, 0xb4, 0xf3, 0x8c, 0x78, 0xd0, 0xd7, 0xbe, 0xd0, 0xcd,
|
||||
0xe2, 0x5f, 0x1c, 0xf5, 0x44, 0x9f, 0xbf, 0x60, 0xb3, 0xc5, 0xf2, 0x6a,
|
||||
0x3d, 0x6d, 0x6e, 0x18, 0xe3, 0x3a, 0xab, 0x43, 0x0b, 0x30, 0xe7, 0x68,
|
||||
0x57, 0xda, 0x89, 0xfe, 0xe9, 0x50, 0x10, 0xdf, 0xef, 0x73, 0x67, 0xd6,
|
||||
0xf9, 0xec, 0x4f, 0x3f, 0x21, 0x73, 0x24, 0x0f, 0xcf, 0xfd, 0xd5, 0xbc,
|
||||
0x5b, 0x1f, 0xcf, 0x59, 0x95, 0xa5, 0x6c, 0xfa, 0x76, 0x66, 0x4e, 0x6d,
|
||||
0x79, 0x75, 0xdf, 0xb7, 0x5d, 0x1e, 0xa0, 0x68, 0xd9, 0x60, 0xce, 0x06,
|
||||
0x1b, 0xda, 0xc1, 0xc1, 0x85, 0x46, 0x2e, 0x8f, 0xd1, 0xcd, 0xde, 0x09,
|
||||
0x61, 0x89, 0x76, 0xc9, 0xd6, 0x9b, 0x5c, 0x1d, 0x9e, 0x79, 0xcc, 0xda,
|
||||
0xa6, 0x76, 0x7a, 0xe9, 0xdd, 0x3d, 0x4d, 0x6b, 0x7a, 0x75, 0x30, 0xbb,
|
||||
0xd3, 0x7b, 0x5f, 0xef, 0xed, 0xa5, 0x7f, 0xac, 0xff, 0x61, 0xa7, 0xbd,
|
||||
0x97, 0x93, 0xdf, 0x28, 0xbd, 0x48, 0x7e, 0xb5, 0x62, 0xed, 0xaf, 0xda,
|
||||
0xb3, 0x9f, 0x78, 0xd8, 0x6a, 0xad, 0xc2, 0x1a, 0xda, 0xad, 0xa5, 0xfa,
|
||||
0x2d, 0x7f, 0x7e, 0xea, 0x36, 0xa7, 0x2b, 0x96, 0x66, 0x27, 0x87, 0xbc,
|
||||
0xc1, 0xb3, 0x0d, 0xbc, 0xe2, 0x5e, 0xfb, 0xa0, 0xe5, 0xf7, 0xe8, 0xff,
|
||||
0xe9, 0x9a, 0x23, 0x2a, 0x63, 0x77, 0x7d, 0x79, 0xc7, 0x05, 0xfc, 0x4f,
|
||||
0xaf, 0x8a, 0xb0, 0x4a, 0x3b, 0xcf, 0xd8, 0x66, 0xfe, 0x4b, 0x5f, 0xf4,
|
||||
0xf5, 0xbe, 0x79, 0x6b, 0xe3, 0xf1, 0xed, 0xc5, 0x8c, 0x51, 0xd7, 0x4f,
|
||||
0xbb, 0xb1, 0xd7, 0xe5, 0xe0, 0x66, 0x27, 0x2f, 0xe6, 0x1e, 0x58, 0x34,
|
||||
0x2a, 0x9b, 0xa2, 0x76, 0xc7, 0x93, 0xa5, 0x2d, 0x6c, 0xbe, 0x57, 0xff,
|
||||
0xe0, 0xa1, 0xf7, 0x87, 0xdd, 0xf9, 0xa0, 0x1c, 0x9d, 0x3e, 0xd9, 0xf3,
|
||||
0x3c, 0xe1, 0x6a, 0xe4, 0xaa, 0x2c, 0x65, 0xa3, 0x7e, 0xab, 0xdd, 0x3b,
|
||||
0xb1, 0x77, 0xe4, 0xec, 0xad, 0x84, 0xe7, 0x08, 0xcf, 0xae, 0x6d, 0xe5,
|
||||
0x7f, 0x94, 0x5e, 0x97, 0xff, 0x8a, 0x7c, 0xb6, 0x7e, 0x77, 0xf7, 0x98,
|
||||
0x35, 0xee, 0xfa, 0xee, 0x16, 0x76, 0xb1, 0x6b, 0x37, 0x57, 0x5f, 0x1e,
|
||||
0xbb, 0xb5, 0x24, 0x95, 0xbd, 0x67, 0xbd, 0xfa, 0x7f, 0x2e, 0x2c, 0xd1,
|
||||
0x2e, 0x79, 0x22, 0x8f, 0xec, 0x7d, 0x53, 0x59, 0xaf, 0xd7, 0x79, 0xe9,
|
||||
0x76, 0x9f, 0x9d, 0xeb, 0xf5, 0x35, 0x47, 0xb4, 0x1d, 0xc3, 0xeb, 0x74,
|
||||
0x9c, 0xb6, 0x1c, 0x71, 0xb6, 0xe1, 0x72, 0x72, 0x4e, 0x40, 0x84, 0x15,
|
||||
0xcb, 0x32, 0xf8, 0xa6, 0xde, 0x3e, 0x99, 0x2b, 0xb7, 0x86, 0x66, 0xc7,
|
||||
0xaf, 0x5c, 0xd7, 0x7a, 0xaa, 0x9f, 0xea, 0xa7, 0x83, 0x8e, 0x31, 0xbd,
|
||||
0x8b, 0x74, 0x46, 0x73, 0x4a, 0xa8, 0x80, 0xbb, 0x2b, 0xae, 0x64, 0x77,
|
||||
0x32, 0x99, 0x66, 0xc0, 0x97, 0xbe, 0xbe, 0xe6, 0xdf, 0xd3, 0xaf, 0x32,
|
||||
0xf2, 0x1f, 0x54, 0xfd, 0x89, 0x20, 0xbe, 0x2c, 0x43, 0xcd, 0xae, 0xbd,
|
||||
0x3f, 0x5e, 0xef, 0xd6, 0xef, 0xf1, 0x77, 0xb7, 0x66, 0xd9, 0xd8, 0xad,
|
||||
0xf5, 0xc7, 0x6c, 0x75, 0xce, 0xd9, 0xba, 0xe1, 0x4f, 0xe9, 0xed, 0xbb,
|
||||
0xb1, 0x61, 0x8c, 0xeb, 0x5c, 0xed, 0xc5, 0x3d, 0x84, 0x96, 0x41, 0xae,
|
||||
0xaf, 0x39, 0x79, 0xea, 0xf2, 0xde, 0xef, 0xb6, 0x94, 0xd2, 0x97, 0x43,
|
||||
0xbb, 0x3f, 0xba, 0x72, 0xb3, 0x16, 0x9c, 0xd0, 0x2e, 0x8e, 0xe0, 0xc2,
|
||||
0x88, 0x20, 0xa5, 0xba, 0x2b, 0xf4, 0xe3, 0x9f, 0xae, 0x1e, 0x16, 0x9c,
|
||||
0x89, 0x96, 0x2e, 0xd4, 0xda, 0xb7, 0xca, 0x58, 0xb7, 0x02, 0xba, 0xd1,
|
||||
0x72, 0x68, 0x09, 0x5a, 0x64, 0x8b, 0x6c, 0x91, 0x2d, 0x72, 0xd8, 0x6a,
|
||||
0x0d, 0x07, 0xd1, 0xd2, 0x85, 0xd5, 0x65, 0x0c, 0x6a, 0x56, 0x47, 0x79,
|
||||
0x88, 0x92, 0x5d, 0xe5, 0x5d, 0x78, 0x53, 0xbd, 0x2b, 0xfd, 0x9a, 0x4c,
|
||||
0x97, 0x1a, 0x34, 0xd4, 0xa0, 0xa1, 0x06, 0x0d, 0x35, 0x68, 0xa8, 0x41,
|
||||
0x43, 0x8d, 0xee, 0x9f, 0xa9, 0x40, 0x83, 0x5f, 0xd4, 0xda, 0x67, 0xf3,
|
||||
0x8c, 0x9b, 0x77, 0x5c, 0x41, 0xc9, 0xb2, 0xd6, 0x77, 0xce, 0xdd, 0xb7,
|
||||
0xed, 0xfe, 0x7c, 0xae, 0x0d, 0x25, 0xc7, 0x72, 0xff, 0x03, 0x96, 0xa7,
|
||||
0xbf, 0x9e, 0xb1, 0xdc, 0x9b, 0xe3, 0xb7, 0xf7, 0x69, 0x12, 0xb7, 0xdf,
|
||||
0xff, 0xe6, 0xc6, 0xa8, 0x99, 0xcf, 0x36, 0xde, 0x6e, 0xf4, 0xd9, 0x61,
|
||||
0x74, 0xce, 0x59, 0x3f, 0xef, 0xf2, 0x72, 0xdc, 0x78, 0xbe, 0x55, 0xa3,
|
||||
0x8d, 0x16, 0xea, 0x1c, 0xec, 0x9a, 0x5c, 0x76, 0x44, 0x17, 0x9c, 0x5f,
|
||||
0x50, 0x52, 0xef, 0x9e, 0xe1, 0xf6, 0xa1, 0x34, 0x57, 0x58, 0x7e, 0xed,
|
||||
0xfe, 0x2e, 0x8a, 0x65, 0xba, 0x6b, 0x37, 0x71, 0x9c, 0x73, 0x1d, 0xc7,
|
||||
0xa6, 0x1f, 0xad, 0xb1, 0xbb, 0xba, 0xd6, 0x56, 0xdb, 0x55, 0xfd, 0x0a,
|
||||
0xc2, 0xc8, 0xa7, 0xab, 0xdb, 0xd7, 0x05, 0x54, 0xca, 0x86, 0x3b, 0xc2,
|
||||
0xad, 0x93, 0x75, 0xad, 0x2f, 0x0f, 0x7a, 0x03, 0x1b, 0x31, 0xb8, 0xb2,
|
||||
0xb1, 0x9c, 0x9a, 0xa3, 0x52, 0xe9, 0x77, 0x02, 0xe5, 0xd1, 0x66, 0x86,
|
||||
0xa6, 0x85, 0xfe, 0xce, 0xc0, 0x81, 0xb2, 0xe2, 0xd6, 0xee, 0x5b, 0xba,
|
||||
0xd3, 0x47, 0x7d, 0x0d, 0xad, 0x0c, 0x8c, 0xe4, 0x80, 0x93, 0xca, 0x5a,
|
||||
0x44, 0x31, 0xa4, 0x44, 0x2f, 0x30, 0x3d, 0x75, 0xd5, 0xb5, 0x21, 0x75,
|
||||
0xfb, 0x8d, 0xe4, 0x91, 0x73, 0x3c, 0x4f, 0x7c, 0xb2, 0x87, 0x45, 0x57,
|
||||
0x39, 0xe0, 0x36, 0x2e, 0xc4, 0xec, 0x8e, 0x2a, 0x9f, 0x3d, 0x5d, 0xdf,
|
||||
0x5e, 0x71, 0xad, 0x38, 0xa2, 0xa3, 0x7e, 0xa7, 0x1b, 0x9f, 0x14, 0x3b,
|
||||
0x50, 0x63, 0x5a, 0xec, 0x4d, 0x8d, 0xdf, 0xfa, 0xc0, 0x75, 0xbc, 0xfe,
|
||||
0x88, 0x43, 0xe9, 0xaa, 0xc5, 0xfd, 0xf7, 0x7e, 0x7e, 0x55, 0x96, 0xb2,
|
||||
0x53, 0x79, 0xb5, 0xae, 0x46, 0xa9, 0xc9, 0x61, 0x15, 0xff, 0x28, 0xf5,
|
||||
0x7d, 0x8c, 0x3f, 0x3d, 0xa1, 0x4e, 0xb9, 0x55, 0x30, 0x8d, 0x03, 0x59,
|
||||
0x80, 0xb9, 0xfa, 0x67, 0xbb, 0x66, 0x8e, 0x2f, 0x32, 0xb2, 0xb6, 0x95,
|
||||
0xb1, 0x9f, 0xd1, 0x2b, 0x15, 0x61, 0x7c, 0xbb, 0x64, 0x51, 0xff, 0xdb,
|
||||
0xd2, 0x0f, 0xfb, 0xe5, 0x78, 0xfe, 0xd2, 0xb7, 0x0f, 0x9a, 0xdd, 0x9b,
|
||||
0x2c, 0x27, 0x4d, 0x2f, 0x85, 0x65, 0x17, 0x8e, 0xf0, 0x76, 0x4f, 0xa8,
|
||||
0xa0, 0x7a, 0xeb, 0xb6, 0x7b, 0xf1, 0x68, 0x86, 0xce, 0x7f, 0x20, 0x4a,
|
||||
0x59, 0xef, 0xcf, 0xa3, 0xf3, 0x5e, 0xfd, 0xca, 0xab, 0xb2, 0x5b, 0xb3,
|
||||
0x6d, 0x37, 0x8d, 0xf9, 0xf3, 0x99, 0x54, 0x56, 0xa6, 0x75, 0x4f, 0x8b,
|
||||
0xbd, 0xc2, 0x02, 0xa8, 0x08, 0x46, 0x15, 0xa9, 0x5d, 0xb8, 0xc6, 0xa4,
|
||||
0xef, 0x9f, 0xfb, 0x41, 0x89, 0xa1, 0xd5, 0x8e, 0xe9, 0x98, 0x52, 0x1e,
|
||||
0x78, 0xc1, 0x61, 0xe1, 0x5c, 0x1a, 0x61, 0x68, 0x5a, 0x90, 0x76, 0xc9,
|
||||
0x51, 0x25, 0x58, 0x92, 0x25, 0x62, 0x20, 0x83, 0x2f, 0x4a, 0x6d, 0x87,
|
||||
0xb2, 0xd2, 0x94, 0x17, 0x5f, 0xe8, 0xc9, 0xdf, 0x14, 0xe3, 0x9e, 0x8d,
|
||||
0xc8, 0x56, 0x69, 0xfc, 0xd6, 0xb9, 0xf1, 0x22, 0x45, 0x4f, 0xaf, 0xf6,
|
||||
0x32, 0x81, 0x24, 0x1a, 0xa4, 0x56, 0x38, 0xaa, 0x94, 0xc6, 0xfc, 0xfd,
|
||||
0x85, 0x63, 0x65, 0x25, 0x8c, 0x6c, 0xa7, 0x34, 0x1e, 0x8e, 0xec, 0x78,
|
||||
0xfb, 0xc8, 0x39, 0x9f, 0xd0, 0xf3, 0x2d, 0xfe, 0x64, 0x4e, 0x9e, 0xf9,
|
||||
0xcd, 0xa3, 0x28, 0xb6, 0xaf, 0xf1, 0xc5, 0x84, 0xf6, 0x91, 0x6f, 0x6b,
|
||||
0xa2, 0xf6, 0xd4, 0x05, 0x2d, 0xa3, 0x6f, 0x55, 0x5d, 0x93, 0xfa, 0xfd,
|
||||
0x3f, 0x75, 0xe9, 0x1b, 0xff, 0x28, 0x27, 0x69, 0x73, 0xd4, 0x68, 0xe4,
|
||||
0xd2, 0xd3, 0x51, 0x03, 0x95, 0x5d, 0xab, 0xfa, 0x1a, 0x1a, 0x6b, 0xeb,
|
||||
0x15, 0xba, 0xf8, 0x99, 0xc5, 0xf4, 0xc2, 0x0b, 0x29, 0xb2, 0xf0, 0xa2,
|
||||
0x33, 0xda, 0xed, 0x76, 0xbb, 0xdd, 0x6e, 0xb7, 0xdb, 0xed, 0x76, 0x7b,
|
||||
0xdb, 0x93, 0x0f, 0x7c, 0x7d, 0x9b, 0x53, 0x1d, 0x54, 0x84, 0x66, 0x5b,
|
||||
0x9d, 0xf1, 0x43, 0xb9, 0xff, 0x86, 0x8a, 0xae, 0xa5, 0xfa, 0xa4, 0xf2,
|
||||
0x5d, 0x3f, 0x7e, 0xe3, 0x12, 0x46, 0x61, 0x6a, 0xea, 0x42, 0x8f, 0x8f,
|
||||
0x5a, 0x50, 0x10, 0xc9, 0x1d, 0x9e, 0xf4, 0xd4, 0xfd, 0x54, 0xed, 0xdb,
|
||||
0x6e, 0x95, 0xa5, 0xfe, 0xc9, 0xc8, 0xac, 0xfe, 0x2b, 0xac, 0x45, 0x30,
|
||||
0x29, 0x66, 0xb4, 0xdb, 0x6d, 0x8d, 0x99, 0x79, 0x97, 0xbf, 0x5e, 0x15,
|
||||
0x4f, 0x05, 0x49, 0xba, 0x93, 0x7b, 0x37, 0x92, 0x76, 0xbb, 0xdd, 0x16,
|
||||
0xeb, 0x61, 0xfc, 0x45, 0x77, 0xf1, 0x6a, 0x3e, 0xa9, 0x75, 0x1b, 0x75,
|
||||
0x53, 0x1b, 0xa5, 0x55, 0x6f, 0xe1, 0xab, 0x96, 0xd1, 0x0f, 0x7e, 0xcd,
|
||||
0x8b, 0x39, 0x1a, 0xf5, 0x84, 0x5f, 0x46, 0x97, 0xb8, 0xd7, 0xac, 0x9f,
|
||||
0x0e, 0xb5, 0xba, 0xa5, 0xb5, 0x86, 0xa6, 0x26, 0x7d, 0xa5, 0xae, 0xe6,
|
||||
0xa0, 0x3e, 0x7a, 0x5b, 0xa7, 0xad, 0xc3, 0x7c, 0x3a, 0x06, 0xa7, 0x6a,
|
||||
0x68, 0x1a, 0xdd, 0x43, 0x1a, 0xf2, 0x4f, 0x5f, 0xfe, 0xdb, 0xbd, 0x67,
|
||||
0x3d, 0xbd, 0xd1, 0x8c, 0xf6, 0xce, 0x61, 0xc5, 0x89, 0x9e, 0x21, 0x0d,
|
||||
0x79, 0xe2, 0x90, 0x86, 0x94, 0x62, 0x48, 0x8f, 0x04, 0xf9, 0xe4, 0xbd,
|
||||
0xf3, 0x61, 0x8b, 0xe3, 0xeb, 0x8b, 0xcd, 0x0f, 0x8d, 0xb5, 0x8c, 0xdc,
|
||||
0xc2, 0xf1, 0xe6, 0xdd, 0x9c, 0x7f, 0xc9, 0x7a, 0x50, 0xae, 0x6d, 0xf6,
|
||||
0x4d, 0x78, 0xf3, 0xee, 0x7f, 0xed, 0xf1, 0xb1, 0xe3, 0x1e, 0x60, 0x52,
|
||||
0xff, 0xe4, 0xc6, 0xc4, 0xdb, 0xfa, 0xfb, 0x07, 0xbb, 0xb6, 0x76, 0xbc,
|
||||
0x89, 0xb9, 0x3f, 0x1c, 0xff, 0x77, 0x57, 0x7e, 0xb1, 0x76, 0x7c, 0x73,
|
||||
0x53, 0x96, 0x3f, 0x7c, 0x3d, 0xcd, 0xca, 0x8b, 0xd3, 0xa7, 0x9a, 0xf6,
|
||||
0xfa, 0xb1, 0xbf, 0x9f, 0x50, 0x3f, 0xec, 0xda, 0xcf, 0xb2, 0xab, 0x6b,
|
||||
0xed, 0x11, 0x2f, 0x1d, 0x12, 0xfb, 0xf2, 0x3b, 0x6c, 0x7c, 0x63, 0x9a,
|
||||
0x7d, 0xb8, 0x5a, 0x3f, 0x5c, 0xff, 0xd5, 0x09, 0xff, 0x32, 0x65, 0x36,
|
||||
0xf8, 0x07, 0x77, 0x2a, 0x9d, 0xb7, 0x3a, 0xf8, 0xee, 0x2d, 0xfd, 0xc7,
|
||||
0x65, 0x1d, 0x9d, 0x5a, 0x59, 0x8f, 0xa7, 0xe7, 0xda, 0xd6, 0x5b, 0x6b,
|
||||
0xbf, 0x47, 0xda, 0x9f, 0x5a, 0x3d, 0x14, 0xeb, 0x5e, 0xfb, 0x33, 0x3b,
|
||||
0x93, 0xa9, 0xe7, 0xfa, 0xc6, 0xd2, 0xa4, 0xc6, 0x0c, 0x76, 0x3f, 0xf7,
|
||||
0x14, 0x1e, 0xa1, 0x1c, 0x3c, 0x81, 0xd9, 0x94, 0xc9, 0x2f, 0xd8, 0x73,
|
||||
0xf0, 0xd5, 0x1d, 0x9d, 0x38, 0x9c, 0x6d, 0x86, 0xf8, 0xe1, 0x62, 0xfa,
|
||||
0xf0, 0x47, 0xf6, 0x66, 0x8e, 0xb6, 0x3d, 0x3c, 0xff, 0xc6, 0xae, 0xc4,
|
||||
0x7e, 0x95, 0x73, 0x11, 0xd9, 0xff, 0x7e, 0x46, 0x1b, 0x95, 0xeb, 0x10,
|
||||
0xd9, 0xda, 0x71, 0xf7, 0x13, 0xc5, 0xd1, 0x1b, 0xe8, 0xcb, 0x96, 0x7a,
|
||||
0xc9, 0x97, 0xb8, 0xbe, 0x32, 0xdd, 0xdb, 0x22, 0x7c, 0xfc, 0x52, 0xc7,
|
||||
0x73, 0xfc, 0xd5, 0xaf, 0xd7, 0xcd, 0x9c, 0x72, 0xca, 0xe8, 0x7e, 0x99,
|
||||
0x7d, 0x67, 0x1f, 0x7f, 0xf9, 0xca, 0x9e, 0xf7, 0x2c, 0xdf, 0x5e, 0xb9,
|
||||
0x3c, 0x38, 0x31, 0xa0, 0xee, 0x23, 0xe3, 0x9b, 0xad, 0xc1, 0xa9, 0x61,
|
||||
0x7f, 0x6b, 0xcd, 0x58, 0x66, 0xe5, 0x95, 0x8b, 0xa2, 0xff, 0x1f, 0xc6,
|
||||
0x7c, 0xc1, 0xdf, 0xd3, 0x5f, 0x18, 0xf3, 0xdd, 0xac, 0xcb, 0x7f, 0x39,
|
||||
0x3c, 0x30, 0x18, 0x9e, 0x0c, 0xae, 0x5b, 0x73, 0x9d, 0x17, 0x3e, 0x44,
|
||||
0x77, 0xfa, 0xd0, 0x60, 0x3c, 0x78, 0xe7, 0x13, 0xbf, 0x9d, 0xca, 0x84,
|
||||
0x95, 0x9e, 0x7f, 0x78, 0x79, 0xad, 0x63, 0x56, 0xd8, 0x84, 0xd4, 0x3a,
|
||||
0xe5, 0x9b, 0x29, 0xdd, 0xe3, 0xa2, 0x67, 0x3c, 0x21, 0x8e, 0x27, 0x0c,
|
||||
0x9d, 0x4d, 0xfb, 0xfd, 0x72, 0xb0, 0x1a, 0xf4, 0x79, 0x1f, 0x78, 0x9b,
|
||||
0xb7, 0xa8, 0xd5, 0x8f, 0x8d, 0x75, 0x74, 0x76, 0x6d, 0xff, 0xe2, 0xf8,
|
||||
0xa3, 0xc7, 0xee, 0x8e, 0x8b, 0xe9, 0x33, 0x8a, 0x8e, 0x1b, 0x83, 0xbd,
|
||||
0x1f, 0x3e, 0xe7, 0xb3, 0xb6, 0xeb, 0xdd, 0x9b, 0x9f, 0x5d, 0xcc, 0x69,
|
||||
0xc6, 0x62, 0x8f, 0x5b, 0x9f, 0x77, 0xb3, 0xbe, 0xb3, 0xcf, 0x9d, 0xfc,
|
||||
0xff, 0x46, 0x5e, 0x0f, 0x70, 0xf8, 0xfb, 0xd6, 0xd7, 0x3c, 0xbc, 0x5a,
|
||||
0xce, 0xad, 0x7d, 0xcd, 0x39, 0x67, 0xfd, 0x3d, 0x97, 0x27, 0x6f, 0xfa,
|
||||
0x66, 0x76, 0xfb, 0x32, 0x82, 0xdb, 0x91, 0xdb, 0xb9, 0xc9, 0xe7, 0xee,
|
||||
0x70, 0xe2, 0x60, 0xf7, 0xb6, 0xd3, 0x43, 0xf8, 0xe2, 0xdb, 0x9a, 0xb7,
|
||||
0x6c, 0xb1, 0xed, 0xf7, 0x6f, 0xf1, 0xde, 0x7d, 0x64, 0x77, 0x07, 0xd3,
|
||||
0xa7, 0x36, 0xfc, 0xe6, 0xa6, 0x26, 0xd7, 0x3e, 0x3a, 0x86, 0x8f, 0x9d,
|
||||
0x11, 0x5d, 0x2b, 0xa3, 0x38, 0xc8, 0xc6, 0x75, 0x38, 0xfb, 0x0c, 0x99,
|
||||
0xd3, 0xb3, 0xbf, 0xce, 0xba, 0x8d, 0xa7, 0x8f, 0xed, 0xde, 0x0d, 0x36,
|
||||
0xaf, 0xa5, 0x70, 0x4c, 0xf7, 0xef, 0x7f, 0x7d, 0xab, 0xe3, 0x1b, 0x72,
|
||||
0xa0, 0xbc, 0x36, 0xc7, 0x38, 0x2c, 0xdc, 0xed, 0xef, 0x4f, 0x7e, 0xe9,
|
||||
0x06, 0xaf, 0x0f, 0x78, 0xf9, 0xe0, 0xf6, 0x8f, 0x1e, 0xea, 0xb8, 0x9b,
|
||||
0x78, 0x87, 0xdb, 0x27, 0x75, 0x55, 0xde, 0x39, 0x68, 0x15, 0xef, 0x08,
|
||||
0xf9, 0xaf, 0x1b, 0x1d, 0xfa, 0xcc, 0xcd, 0x71, 0x71, 0x00, 0xdc, 0x2e,
|
||||
0xbf, 0xc0, 0x2f, 0x73, 0x60, 0x9f, 0x73, 0xf4, 0x1f, 0x93, 0xf9, 0x0b,
|
||||
0xf6, 0x8f, 0xdb, 0xfb, 0x12, 0x3e, 0x8a, 0x83, 0x00, 0xa7, 0x1b, 0x6f,
|
||||
0x76, 0x40, 0x5c, 0xe7, 0x7f, 0x02, 0xb9, 0xf3, 0x85, 0x79, 0x6b, 0x0f,
|
||||
0x79, 0x6b, 0x79
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
+1778
File diff suppressed because it is too large
Load Diff
+409
@@ -0,0 +1,409 @@
|
||||
// basisu_backend.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include "../transcoder/basisu.h"
|
||||
#include "basisu_enc.h"
|
||||
#include "../transcoder/basisu_transcoder_internal.h"
|
||||
#include "basisu_frontend.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
struct etc1_selector_palette_entry
|
||||
{
|
||||
etc1_selector_palette_entry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
basisu::clear_obj(*this);
|
||||
}
|
||||
|
||||
uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
|
||||
uint8_t& operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
|
||||
|
||||
void set_uint32(uint32_t v)
|
||||
{
|
||||
for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
|
||||
{
|
||||
uint32_t b = (v >> (byte_index * 8)) & 0xFF;
|
||||
|
||||
m_selectors[byte_index * 4 + 0] = b & 3;
|
||||
m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
|
||||
m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
|
||||
m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_uint32() const
|
||||
{
|
||||
return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
|
||||
}
|
||||
|
||||
uint32_t get_byte(uint32_t byte_index) const
|
||||
{
|
||||
assert(byte_index < 4);
|
||||
|
||||
return m_selectors[byte_index * 4 + 0] |
|
||||
(m_selectors[byte_index * 4 + 1] << 2) |
|
||||
(m_selectors[byte_index * 4 + 2] << 4) |
|
||||
(m_selectors[byte_index * 4 + 3] << 6);
|
||||
}
|
||||
|
||||
uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
|
||||
uint8_t& operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
|
||||
|
||||
bool operator< (const etc1_selector_palette_entry& other) const
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (m_selectors[i] < other.m_selectors[i])
|
||||
return true;
|
||||
else if (m_selectors[i] != other.m_selectors[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator== (const etc1_selector_palette_entry& other) const
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (m_selectors[i] != other.m_selectors[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_selectors[16];
|
||||
};
|
||||
|
||||
typedef basisu::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
|
||||
|
||||
struct encoder_block
|
||||
{
|
||||
encoder_block()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
uint32_t m_endpoint_predictor;
|
||||
|
||||
int m_endpoint_index;
|
||||
int m_selector_index;
|
||||
|
||||
int m_selector_history_buf_index;
|
||||
|
||||
bool m_is_cr_target;
|
||||
void clear()
|
||||
{
|
||||
m_endpoint_predictor = 0;
|
||||
|
||||
m_endpoint_index = 0;
|
||||
m_selector_index = 0;
|
||||
|
||||
m_selector_history_buf_index = 0;
|
||||
m_is_cr_target = false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef basisu::vector<encoder_block> encoder_block_vec;
|
||||
typedef vector2D<encoder_block> encoder_block_vec2D;
|
||||
|
||||
struct etc1_endpoint_palette_entry
|
||||
{
|
||||
etc1_endpoint_palette_entry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
color_rgba m_color5;
|
||||
uint32_t m_inten5;
|
||||
bool m_color5_valid;
|
||||
|
||||
void clear()
|
||||
{
|
||||
clear_obj(*this);
|
||||
}
|
||||
};
|
||||
|
||||
typedef basisu::vector<etc1_endpoint_palette_entry> etc1_endpoint_palette_entry_vec;
|
||||
|
||||
struct basisu_backend_params
|
||||
{
|
||||
bool m_etc1s;
|
||||
bool m_debug, m_debug_images;
|
||||
float m_endpoint_rdo_quality_thresh;
|
||||
float m_selector_rdo_quality_thresh;
|
||||
uint32_t m_compression_level;
|
||||
|
||||
bool m_used_global_codebooks;
|
||||
|
||||
bool m_validate;
|
||||
|
||||
basisu_backend_params()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_etc1s = false;
|
||||
m_debug = false;
|
||||
m_debug_images = false;
|
||||
m_endpoint_rdo_quality_thresh = 0.0f;
|
||||
m_selector_rdo_quality_thresh = 0.0f;
|
||||
m_compression_level = 0;
|
||||
m_used_global_codebooks = false;
|
||||
m_validate = true;
|
||||
}
|
||||
};
|
||||
|
||||
struct basisu_backend_slice_desc
|
||||
{
|
||||
basisu_backend_slice_desc()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
clear_obj(*this);
|
||||
}
|
||||
|
||||
uint32_t m_first_block_index;
|
||||
|
||||
uint32_t m_orig_width;
|
||||
uint32_t m_orig_height;
|
||||
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
uint32_t m_num_blocks_x;
|
||||
uint32_t m_num_blocks_y;
|
||||
|
||||
uint32_t m_num_macroblocks_x;
|
||||
uint32_t m_num_macroblocks_y;
|
||||
|
||||
uint32_t m_source_file_index; // also the basis image index
|
||||
uint32_t m_mip_index;
|
||||
bool m_alpha;
|
||||
bool m_iframe;
|
||||
};
|
||||
|
||||
typedef basisu::vector<basisu_backend_slice_desc> basisu_backend_slice_desc_vec;
|
||||
|
||||
struct basisu_backend_output
|
||||
{
|
||||
basist::basis_tex_format m_tex_format;
|
||||
|
||||
bool m_etc1s;
|
||||
bool m_uses_global_codebooks;
|
||||
bool m_srgb;
|
||||
|
||||
uint32_t m_num_endpoints;
|
||||
uint32_t m_num_selectors;
|
||||
|
||||
uint8_vec m_endpoint_palette;
|
||||
uint8_vec m_selector_palette;
|
||||
|
||||
basisu_backend_slice_desc_vec m_slice_desc;
|
||||
|
||||
uint8_vec m_slice_image_tables;
|
||||
basisu::vector<uint8_vec> m_slice_image_data;
|
||||
uint16_vec m_slice_image_crcs;
|
||||
|
||||
basisu_backend_output()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_tex_format = basist::basis_tex_format::cETC1S;
|
||||
m_etc1s = false;
|
||||
m_uses_global_codebooks = false;
|
||||
m_srgb = true;
|
||||
|
||||
m_num_endpoints = 0;
|
||||
m_num_selectors = 0;
|
||||
|
||||
m_endpoint_palette.clear();
|
||||
m_selector_palette.clear();
|
||||
m_slice_desc.clear();
|
||||
m_slice_image_tables.clear();
|
||||
m_slice_image_data.clear();
|
||||
m_slice_image_crcs.clear();
|
||||
}
|
||||
|
||||
uint32_t get_output_size_estimate() const
|
||||
{
|
||||
uint32_t total_compressed_bytes = (uint32_t)(m_slice_image_tables.size() + m_endpoint_palette.size() + m_selector_palette.size());
|
||||
for (uint32_t i = 0; i < m_slice_image_data.size(); i++)
|
||||
total_compressed_bytes += (uint32_t)m_slice_image_data[i].size();
|
||||
|
||||
return total_compressed_bytes;
|
||||
}
|
||||
};
|
||||
|
||||
class basisu_backend
|
||||
{
|
||||
BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_backend);
|
||||
|
||||
public:
|
||||
|
||||
basisu_backend();
|
||||
|
||||
void clear();
|
||||
|
||||
void init(basisu_frontend *pFront_end, basisu_backend_params ¶ms, const basisu_backend_slice_desc_vec &slice_desc);
|
||||
|
||||
uint32_t encode();
|
||||
|
||||
const basisu_backend_output &get_output() const { return m_output; }
|
||||
const basisu_backend_params& get_params() const { return m_params; }
|
||||
|
||||
private:
|
||||
basisu_frontend *m_pFront_end;
|
||||
basisu_backend_params m_params;
|
||||
basisu_backend_slice_desc_vec m_slices;
|
||||
basisu_backend_output m_output;
|
||||
|
||||
etc1_endpoint_palette_entry_vec m_endpoint_palette;
|
||||
etc1_selector_palette_entry_vec m_selector_palette;
|
||||
|
||||
struct etc1_global_selector_cb_entry_desc
|
||||
{
|
||||
uint32_t m_pal_index;
|
||||
uint32_t m_mod_index;
|
||||
bool m_was_used;
|
||||
};
|
||||
|
||||
typedef basisu::vector<etc1_global_selector_cb_entry_desc> etc1_global_selector_cb_entry_desc_vec;
|
||||
|
||||
etc1_global_selector_cb_entry_desc_vec m_global_selector_palette_desc;
|
||||
|
||||
basisu::vector<encoder_block_vec2D> m_slice_encoder_blocks;
|
||||
|
||||
// Maps OLD to NEW endpoint/selector indices
|
||||
uint_vec m_endpoint_remap_table_old_to_new;
|
||||
uint_vec m_endpoint_remap_table_new_to_old;
|
||||
bool_vec m_old_endpoint_was_used;
|
||||
bool_vec m_new_endpoint_was_used;
|
||||
|
||||
uint_vec m_selector_remap_table_old_to_new;
|
||||
|
||||
// Maps NEW to OLD endpoint/selector indices
|
||||
uint_vec m_selector_remap_table_new_to_old;
|
||||
|
||||
uint32_t get_total_slices() const
|
||||
{
|
||||
return (uint32_t)m_slices.size();
|
||||
}
|
||||
|
||||
uint32_t get_total_slice_blocks() const
|
||||
{
|
||||
return m_pFront_end->get_total_output_blocks();
|
||||
}
|
||||
|
||||
uint32_t get_block_index(uint32_t slice_index, uint32_t block_x, uint32_t block_y) const
|
||||
{
|
||||
const basisu_backend_slice_desc &slice = m_slices[slice_index];
|
||||
|
||||
assert((block_x < slice.m_num_blocks_x) && (block_y < slice.m_num_blocks_y));
|
||||
|
||||
return slice.m_first_block_index + block_y * slice.m_num_blocks_x + block_x;
|
||||
}
|
||||
|
||||
uint32_t get_total_blocks(uint32_t slice_index) const
|
||||
{
|
||||
return m_slices[slice_index].m_num_blocks_x * m_slices[slice_index].m_num_blocks_y;
|
||||
}
|
||||
|
||||
uint32_t get_total_blocks() const
|
||||
{
|
||||
uint32_t total_blocks = 0;
|
||||
for (uint32_t i = 0; i < m_slices.size(); i++)
|
||||
total_blocks += get_total_blocks(i);
|
||||
return total_blocks;
|
||||
}
|
||||
|
||||
// Returns the total number of input texels, not counting padding up to blocks/macroblocks.
|
||||
uint32_t get_total_input_texels(uint32_t slice_index) const
|
||||
{
|
||||
return m_slices[slice_index].m_orig_width * m_slices[slice_index].m_orig_height;
|
||||
}
|
||||
|
||||
uint32_t get_total_input_texels() const
|
||||
{
|
||||
uint32_t total_texels = 0;
|
||||
for (uint32_t i = 0; i < m_slices.size(); i++)
|
||||
total_texels += get_total_input_texels(i);
|
||||
return total_texels;
|
||||
}
|
||||
|
||||
int find_slice(uint32_t block_index, uint32_t *pBlock_x, uint32_t *pBlock_y) const
|
||||
{
|
||||
for (uint32_t i = 0; i < m_slices.size(); i++)
|
||||
{
|
||||
if ((block_index >= m_slices[i].m_first_block_index) && (block_index < (m_slices[i].m_first_block_index + m_slices[i].m_num_blocks_x * m_slices[i].m_num_blocks_y)))
|
||||
{
|
||||
const uint32_t ofs = block_index - m_slices[i].m_first_block_index;
|
||||
const uint32_t x = ofs % m_slices[i].m_num_blocks_x;
|
||||
const uint32_t y = ofs / m_slices[i].m_num_blocks_x;
|
||||
|
||||
if (pBlock_x) *pBlock_x = x;
|
||||
if (pBlock_y) *pBlock_y = y;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void create_endpoint_palette();
|
||||
|
||||
void create_selector_palette();
|
||||
|
||||
// endpoint palette
|
||||
// 5:5:5 and predicted 4:4:4 colors, 1 or 2 3-bit intensity table indices
|
||||
// selector palette
|
||||
// 4x4 2-bit selectors
|
||||
|
||||
// per-macroblock:
|
||||
// 4 diff bits
|
||||
// 4 flip bits
|
||||
// Endpoint template index, 1-8 endpoint indices
|
||||
// Alternately, if no template applies, we can send 4 ETC1S bits followed by 4-8 endpoint indices
|
||||
// 4 selector indices
|
||||
|
||||
void reoptimize_and_sort_endpoints_codebook(uint32_t total_block_endpoints_remapped, uint_vec &all_endpoint_indices);
|
||||
void sort_selector_codebook();
|
||||
void create_encoder_blocks();
|
||||
void compute_slice_crcs();
|
||||
bool encode_image();
|
||||
bool encode_endpoint_palette();
|
||||
bool encode_selector_palette();
|
||||
int find_video_frame(int slice_index, int delta);
|
||||
void check_for_valid_cr_blocks();
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
// basisu_basis_file.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_basis_file.h"
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
|
||||
// The output file version. Keep in sync with BASISD_SUPPORTED_BASIS_VERSION.
|
||||
#define BASIS_FILE_VERSION (0x13)
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
void basisu_file::create_header(const basisu_backend_output &encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame)
|
||||
{
|
||||
m_header.m_header_size = sizeof(basist::basis_file_header);
|
||||
|
||||
m_header.m_data_size = m_total_file_size - sizeof(basist::basis_file_header);
|
||||
|
||||
m_header.m_total_slices = (uint32_t)encoder_output.m_slice_desc.size();
|
||||
|
||||
m_header.m_total_images = 0;
|
||||
for (uint32_t i = 0; i < encoder_output.m_slice_desc.size(); i++)
|
||||
m_header.m_total_images = maximum<uint32_t>(m_header.m_total_images, encoder_output.m_slice_desc[i].m_source_file_index + 1);
|
||||
|
||||
m_header.m_tex_format = (int)encoder_output.m_tex_format;
|
||||
m_header.m_flags = 0;
|
||||
|
||||
if (encoder_output.m_etc1s)
|
||||
{
|
||||
assert(encoder_output.m_tex_format == basist::basis_tex_format::cETC1S);
|
||||
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagETC1S;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(encoder_output.m_tex_format != basist::basis_tex_format::cETC1S);
|
||||
}
|
||||
|
||||
if (y_flipped)
|
||||
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagYFlipped;
|
||||
if (encoder_output.m_uses_global_codebooks)
|
||||
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagUsesGlobalCodebook;
|
||||
if (encoder_output.m_srgb)
|
||||
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagSRGB;
|
||||
|
||||
for (uint32_t i = 0; i < encoder_output.m_slice_desc.size(); i++)
|
||||
{
|
||||
if (encoder_output.m_slice_desc[i].m_alpha)
|
||||
{
|
||||
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagHasAlphaSlices;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_header.m_tex_type = static_cast<uint8_t>(tex_type);
|
||||
m_header.m_us_per_frame = clamp<uint32_t>(us_per_frame, 0, basist::cBASISMaxUSPerFrame);
|
||||
|
||||
m_header.m_userdata0 = userdata0;
|
||||
m_header.m_userdata1 = userdata1;
|
||||
|
||||
m_header.m_total_endpoints = encoder_output.m_num_endpoints;
|
||||
if (!encoder_output.m_uses_global_codebooks)
|
||||
{
|
||||
m_header.m_endpoint_cb_file_ofs = m_endpoint_cb_file_ofs;
|
||||
m_header.m_endpoint_cb_file_size = (uint32_t)encoder_output.m_endpoint_palette.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!m_endpoint_cb_file_ofs);
|
||||
}
|
||||
|
||||
m_header.m_total_selectors = encoder_output.m_num_selectors;
|
||||
if (!encoder_output.m_uses_global_codebooks)
|
||||
{
|
||||
m_header.m_selector_cb_file_ofs = m_selector_cb_file_ofs;
|
||||
m_header.m_selector_cb_file_size = (uint32_t)encoder_output.m_selector_palette.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!m_selector_cb_file_ofs);
|
||||
}
|
||||
|
||||
m_header.m_tables_file_ofs = m_tables_file_ofs;
|
||||
m_header.m_tables_file_size = (uint32_t)encoder_output.m_slice_image_tables.size();
|
||||
|
||||
m_header.m_slice_desc_file_ofs = m_slice_descs_file_ofs;
|
||||
}
|
||||
|
||||
bool basisu_file::create_image_descs(const basisu_backend_output &encoder_output)
|
||||
{
|
||||
const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
|
||||
|
||||
m_images_descs.resize(slice_descs.size());
|
||||
|
||||
uint64_t cur_slice_file_ofs = m_first_image_file_ofs;
|
||||
for (uint32_t i = 0; i < slice_descs.size(); i++)
|
||||
{
|
||||
clear_obj(m_images_descs[i]);
|
||||
|
||||
m_images_descs[i].m_image_index = slice_descs[i].m_source_file_index;
|
||||
m_images_descs[i].m_level_index = slice_descs[i].m_mip_index;
|
||||
|
||||
if (slice_descs[i].m_alpha)
|
||||
m_images_descs[i].m_flags = m_images_descs[i].m_flags | basist::cSliceDescFlagsHasAlpha;
|
||||
if (slice_descs[i].m_iframe)
|
||||
m_images_descs[i].m_flags = m_images_descs[i].m_flags | basist::cSliceDescFlagsFrameIsIFrame;
|
||||
|
||||
m_images_descs[i].m_orig_width = slice_descs[i].m_orig_width;
|
||||
m_images_descs[i].m_orig_height = slice_descs[i].m_orig_height;
|
||||
m_images_descs[i].m_num_blocks_x = slice_descs[i].m_num_blocks_x;
|
||||
m_images_descs[i].m_num_blocks_y = slice_descs[i].m_num_blocks_y;
|
||||
m_images_descs[i].m_slice_data_crc16 = encoder_output.m_slice_image_crcs[i];
|
||||
|
||||
if (encoder_output.m_slice_image_data[i].size() > UINT32_MAX)
|
||||
{
|
||||
error_printf("basisu_file::create_image_descs: Basis file too large\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t image_size = (uint32_t)encoder_output.m_slice_image_data[i].size();
|
||||
|
||||
m_images_descs[i].m_file_ofs = (uint32_t)cur_slice_file_ofs;
|
||||
m_images_descs[i].m_file_size = image_size;
|
||||
|
||||
cur_slice_file_ofs += image_size;
|
||||
if (cur_slice_file_ofs > UINT32_MAX)
|
||||
{
|
||||
error_printf("basisu_file::create_image_descs: Basis file too large\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
assert(cur_slice_file_ofs == m_total_file_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void basisu_file::create_comp_data(const basisu_backend_output &encoder_output)
|
||||
{
|
||||
const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
|
||||
|
||||
append_vector(m_comp_data, reinterpret_cast<const uint8_t *>(&m_header), sizeof(m_header));
|
||||
|
||||
assert(m_comp_data.size() == m_slice_descs_file_ofs);
|
||||
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&m_images_descs[0]), m_images_descs.size() * sizeof(m_images_descs[0]));
|
||||
|
||||
if (!encoder_output.m_uses_global_codebooks)
|
||||
{
|
||||
if (encoder_output.m_endpoint_palette.size())
|
||||
{
|
||||
assert(m_comp_data.size() == m_endpoint_cb_file_ofs);
|
||||
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_endpoint_palette[0]), encoder_output.m_endpoint_palette.size());
|
||||
}
|
||||
|
||||
if (encoder_output.m_selector_palette.size())
|
||||
{
|
||||
assert(m_comp_data.size() == m_selector_cb_file_ofs);
|
||||
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_selector_palette[0]), encoder_output.m_selector_palette.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (encoder_output.m_slice_image_tables.size())
|
||||
{
|
||||
assert(m_comp_data.size() == m_tables_file_ofs);
|
||||
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_slice_image_tables[0]), encoder_output.m_slice_image_tables.size());
|
||||
}
|
||||
|
||||
assert(m_comp_data.size() == m_first_image_file_ofs);
|
||||
for (uint32_t i = 0; i < slice_descs.size(); i++)
|
||||
append_vector(m_comp_data, &encoder_output.m_slice_image_data[i][0], encoder_output.m_slice_image_data[i].size());
|
||||
|
||||
assert(m_comp_data.size() == m_total_file_size);
|
||||
}
|
||||
|
||||
void basisu_file::fixup_crcs()
|
||||
{
|
||||
basist::basis_file_header *pHeader = reinterpret_cast<basist::basis_file_header *>(&m_comp_data[0]);
|
||||
|
||||
pHeader->m_data_size = m_total_file_size - sizeof(basist::basis_file_header);
|
||||
pHeader->m_data_crc16 = basist::crc16(&m_comp_data[0] + sizeof(basist::basis_file_header), m_total_file_size - sizeof(basist::basis_file_header), 0);
|
||||
|
||||
pHeader->m_header_crc16 = basist::crc16(&pHeader->m_data_size, sizeof(basist::basis_file_header) - BASISU_OFFSETOF(basist::basis_file_header, m_data_size), 0);
|
||||
|
||||
pHeader->m_sig = basist::basis_file_header::cBASISSigValue;
|
||||
pHeader->m_ver = BASIS_FILE_VERSION;// basist::basis_file_header::cBASISFirstVersion;
|
||||
}
|
||||
|
||||
bool basisu_file::init(const basisu_backend_output &encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame)
|
||||
{
|
||||
clear();
|
||||
|
||||
const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
|
||||
|
||||
// The Basis file uses 32-bit fields for lots of stuff, so make sure it's not too large.
|
||||
uint64_t check_size = 0;
|
||||
if (!encoder_output.m_uses_global_codebooks)
|
||||
{
|
||||
check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
|
||||
(uint64_t)encoder_output.m_endpoint_palette.size() + (uint64_t)encoder_output.m_selector_palette.size() + (uint64_t)encoder_output.m_slice_image_tables.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
|
||||
(uint64_t)encoder_output.m_slice_image_tables.size();
|
||||
}
|
||||
if (check_size >= 0xFFFF0000ULL)
|
||||
{
|
||||
error_printf("basisu_file::init: File is too large!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_header_file_ofs = 0;
|
||||
m_slice_descs_file_ofs = sizeof(basist::basis_file_header);
|
||||
if (encoder_output.m_tex_format == basist::basis_tex_format::cETC1S)
|
||||
{
|
||||
if (encoder_output.m_uses_global_codebooks)
|
||||
{
|
||||
m_endpoint_cb_file_ofs = 0;
|
||||
m_selector_cb_file_ofs = 0;
|
||||
m_tables_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_endpoint_cb_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
|
||||
m_selector_cb_file_ofs = m_endpoint_cb_file_ofs + (uint32_t)encoder_output.m_endpoint_palette.size();
|
||||
m_tables_file_ofs = m_selector_cb_file_ofs + (uint32_t)encoder_output.m_selector_palette.size();
|
||||
}
|
||||
m_first_image_file_ofs = m_tables_file_ofs + (uint32_t)encoder_output.m_slice_image_tables.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_endpoint_cb_file_ofs = 0;
|
||||
m_selector_cb_file_ofs = 0;
|
||||
m_tables_file_ofs = 0;
|
||||
m_first_image_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
|
||||
}
|
||||
|
||||
uint64_t total_file_size = m_first_image_file_ofs;
|
||||
for (uint32_t i = 0; i < encoder_output.m_slice_image_data.size(); i++)
|
||||
total_file_size += encoder_output.m_slice_image_data[i].size();
|
||||
if (total_file_size >= 0xFFFF0000ULL)
|
||||
{
|
||||
error_printf("basisu_file::init: File is too large!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_total_file_size = (uint32_t)total_file_size;
|
||||
|
||||
create_header(encoder_output, tex_type, userdata0, userdata1, y_flipped, us_per_frame);
|
||||
|
||||
if (!create_image_descs(encoder_output))
|
||||
return false;
|
||||
|
||||
create_comp_data(encoder_output);
|
||||
|
||||
fixup_crcs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// basisu_basis_file.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "../transcoder/basisu_file_headers.h"
|
||||
#include "basisu_backend.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
class basisu_file
|
||||
{
|
||||
BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_file);
|
||||
|
||||
public:
|
||||
basisu_file()
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_comp_data.clear();
|
||||
|
||||
clear_obj(m_header);
|
||||
m_images_descs.clear();
|
||||
|
||||
m_header_file_ofs = 0;
|
||||
m_slice_descs_file_ofs = 0;
|
||||
m_endpoint_cb_file_ofs = 0;
|
||||
m_selector_cb_file_ofs = 0;
|
||||
m_tables_file_ofs = 0;
|
||||
m_first_image_file_ofs = 0;
|
||||
m_total_file_size = 0;
|
||||
}
|
||||
|
||||
bool init(const basisu_backend_output& encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame);
|
||||
|
||||
const uint8_vec &get_compressed_data() const { return m_comp_data; }
|
||||
|
||||
private:
|
||||
basist::basis_file_header m_header;
|
||||
basisu::vector<basist::basis_slice_desc> m_images_descs;
|
||||
|
||||
uint8_vec m_comp_data;
|
||||
|
||||
uint32_t m_header_file_ofs;
|
||||
uint32_t m_slice_descs_file_ofs;
|
||||
uint32_t m_endpoint_cb_file_ofs;
|
||||
uint32_t m_selector_cb_file_ofs;
|
||||
uint32_t m_tables_file_ofs;
|
||||
uint32_t m_first_image_file_ofs;
|
||||
uint32_t m_total_file_size;
|
||||
|
||||
void create_header(const basisu_backend_output& encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame);
|
||||
bool create_image_descs(const basisu_backend_output& encoder_output);
|
||||
void create_comp_data(const basisu_backend_output& encoder_output);
|
||||
void fixup_crcs();
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
+1992
File diff suppressed because it is too large
Load Diff
+132
@@ -0,0 +1,132 @@
|
||||
// File: basisu_bc7enc.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "../transcoder/basisu_transcoder_uastc.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
|
||||
#define BC7ENC_MAX_PARTITIONS1 (64)
|
||||
#define BC7ENC_MAX_UBER_LEVEL (4)
|
||||
|
||||
typedef uint8_t bc7enc_bool;
|
||||
|
||||
#define BC7ENC_TRUE (1)
|
||||
#define BC7ENC_FALSE (0)
|
||||
|
||||
typedef struct { float m_c[4]; } bc7enc_vec4F;
|
||||
|
||||
extern const float g_bc7_weights1x[2 * 4];
|
||||
extern const float g_bc7_weights2x[4 * 4];
|
||||
extern const float g_bc7_weights3x[8 * 4];
|
||||
extern const float g_bc7_weights4x[16 * 4];
|
||||
extern const float g_astc_weights4x[16 * 4];
|
||||
extern const float g_astc_weights5x[32 * 4];
|
||||
extern const float g_astc_weights_3levelsx[3 * 4];
|
||||
|
||||
extern basist::astc_quant_bin g_astc_sorted_order_unquant[basist::BC7ENC_TOTAL_ASTC_RANGES][256]; // [sorted unquantized order]
|
||||
|
||||
struct color_cell_compressor_params
|
||||
{
|
||||
uint32_t m_num_pixels;
|
||||
const basist::color_quad_u8* m_pPixels;
|
||||
|
||||
uint32_t m_num_selector_weights;
|
||||
const uint32_t* m_pSelector_weights;
|
||||
|
||||
const bc7enc_vec4F* m_pSelector_weightsx;
|
||||
uint32_t m_comp_bits;
|
||||
|
||||
const uint8_t *m_pForce_selectors;
|
||||
|
||||
// Non-zero m_astc_endpoint_range enables ASTC mode. m_comp_bits and m_has_pbits are always false. We only support 2, 3, or 4 bit weight encodings.
|
||||
uint32_t m_astc_endpoint_range;
|
||||
|
||||
uint32_t m_weights[4];
|
||||
bc7enc_bool m_has_alpha;
|
||||
bc7enc_bool m_has_pbits;
|
||||
bc7enc_bool m_endpoints_share_pbit;
|
||||
bc7enc_bool m_perceptual;
|
||||
};
|
||||
|
||||
struct color_cell_compressor_results
|
||||
{
|
||||
uint64_t m_best_overall_err;
|
||||
basist::color_quad_u8 m_low_endpoint;
|
||||
basist::color_quad_u8 m_high_endpoint;
|
||||
uint32_t m_pbits[2];
|
||||
uint8_t* m_pSelectors;
|
||||
uint8_t* m_pSelectors_temp;
|
||||
|
||||
// Encoded ASTC indices, if ASTC mode is enabled
|
||||
basist::color_quad_u8 m_astc_low_endpoint;
|
||||
basist::color_quad_u8 m_astc_high_endpoint;
|
||||
};
|
||||
|
||||
struct bc7enc_compress_block_params
|
||||
{
|
||||
// m_max_partitions_mode1 may range from 0 (disables mode 1) to BC7ENC_MAX_PARTITIONS1. The higher this value, the slower the compressor, but the higher the quality.
|
||||
uint32_t m_max_partitions_mode1;
|
||||
|
||||
// Relative RGBA or YCbCrA weights.
|
||||
uint32_t m_weights[4];
|
||||
|
||||
// m_uber_level may range from 0 to BC7ENC_MAX_UBER_LEVEL. The higher this value, the slower the compressor, but the higher the quality.
|
||||
uint32_t m_uber_level;
|
||||
|
||||
// If m_perceptual is true, colorspace error is computed in YCbCr space, otherwise RGB.
|
||||
bc7enc_bool m_perceptual;
|
||||
|
||||
uint32_t m_least_squares_passes;
|
||||
};
|
||||
|
||||
uint64_t color_cell_compression(uint32_t mode, const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, const bc7enc_compress_block_params* pComp_params);
|
||||
|
||||
uint64_t color_cell_compression_est_astc(
|
||||
uint32_t num_weights, uint32_t num_comps, const uint32_t* pWeight_table,
|
||||
uint32_t num_pixels, const basist::color_quad_u8* pPixels,
|
||||
uint64_t best_err_so_far, const uint32_t weights[4]);
|
||||
|
||||
inline void bc7enc_compress_block_params_init_linear_weights(bc7enc_compress_block_params* p)
|
||||
{
|
||||
p->m_perceptual = BC7ENC_FALSE;
|
||||
p->m_weights[0] = 1;
|
||||
p->m_weights[1] = 1;
|
||||
p->m_weights[2] = 1;
|
||||
p->m_weights[3] = 1;
|
||||
}
|
||||
|
||||
inline void bc7enc_compress_block_params_init_perceptual_weights(bc7enc_compress_block_params* p)
|
||||
{
|
||||
p->m_perceptual = BC7ENC_TRUE;
|
||||
p->m_weights[0] = 128;
|
||||
p->m_weights[1] = 64;
|
||||
p->m_weights[2] = 16;
|
||||
p->m_weights[3] = 32;
|
||||
}
|
||||
|
||||
inline void bc7enc_compress_block_params_init(bc7enc_compress_block_params* p)
|
||||
{
|
||||
p->m_max_partitions_mode1 = BC7ENC_MAX_PARTITIONS1;
|
||||
p->m_least_squares_passes = 1;
|
||||
p->m_uber_level = 0;
|
||||
bc7enc_compress_block_params_init_perceptual_weights(p);
|
||||
}
|
||||
|
||||
// bc7enc_compress_block_init() MUST be called before calling bc7enc_compress_block() (or you'll get artifacts).
|
||||
void bc7enc_compress_block_init();
|
||||
|
||||
} // namespace basisu
|
||||
+2390
File diff suppressed because it is too large
Load Diff
+644
@@ -0,0 +1,644 @@
|
||||
// basisu_comp.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "basisu_frontend.h"
|
||||
#include "basisu_backend.h"
|
||||
#include "basisu_basis_file.h"
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
#include "basisu_uastc_enc.h"
|
||||
|
||||
#define BASISU_LIB_VERSION 116
|
||||
#define BASISU_LIB_VERSION_STRING "1.16"
|
||||
|
||||
#ifndef BASISD_SUPPORT_KTX2
|
||||
#error BASISD_SUPPORT_KTX2 is undefined
|
||||
#endif
|
||||
#ifndef BASISD_SUPPORT_KTX2_ZSTD
|
||||
#error BASISD_SUPPORT_KTX2_ZSTD is undefined
|
||||
#endif
|
||||
|
||||
#if !BASISD_SUPPORT_KTX2
|
||||
#error BASISD_SUPPORT_KTX2 must be enabled when building the encoder. To reduce code size if KTX2 support is not needed, set BASISD_SUPPORT_KTX2_ZSTD to 0
|
||||
#endif
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
struct opencl_context;
|
||||
typedef opencl_context* opencl_context_ptr;
|
||||
|
||||
const uint32_t BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION = 16384;
|
||||
|
||||
// Allow block's color distance to increase by 1.5 while searching for an alternative nearby endpoint.
|
||||
const float BASISU_DEFAULT_ENDPOINT_RDO_THRESH = 1.5f;
|
||||
|
||||
// Allow block's color distance to increase by 1.25 while searching the selector history buffer for a close enough match.
|
||||
const float BASISU_DEFAULT_SELECTOR_RDO_THRESH = 1.25f;
|
||||
|
||||
const int BASISU_DEFAULT_QUALITY = 128;
|
||||
const float BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH = 2.0f;
|
||||
|
||||
const uint32_t BASISU_MAX_IMAGE_DIMENSION = 16384;
|
||||
const uint32_t BASISU_QUALITY_MIN = 1;
|
||||
const uint32_t BASISU_QUALITY_MAX = 255;
|
||||
const uint32_t BASISU_MAX_ENDPOINT_CLUSTERS = basisu_frontend::cMaxEndpointClusters;
|
||||
const uint32_t BASISU_MAX_SELECTOR_CLUSTERS = basisu_frontend::cMaxSelectorClusters;
|
||||
|
||||
const uint32_t BASISU_MAX_SLICES = 0xFFFFFF;
|
||||
|
||||
const int BASISU_RDO_UASTC_DICT_SIZE_DEFAULT = 4096; // 32768;
|
||||
const int BASISU_RDO_UASTC_DICT_SIZE_MIN = 64;
|
||||
const int BASISU_RDO_UASTC_DICT_SIZE_MAX = 65536;
|
||||
|
||||
struct image_stats
|
||||
{
|
||||
image_stats()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_filename.clear();
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
|
||||
m_basis_rgb_avg_psnr = 0.0f;
|
||||
m_basis_rgba_avg_psnr = 0.0f;
|
||||
m_basis_a_avg_psnr = 0.0f;
|
||||
m_basis_luma_709_psnr = 0.0f;
|
||||
m_basis_luma_601_psnr = 0.0f;
|
||||
m_basis_luma_709_ssim = 0.0f;
|
||||
|
||||
m_bc7_rgb_avg_psnr = 0.0f;
|
||||
m_bc7_rgba_avg_psnr = 0.0f;
|
||||
m_bc7_a_avg_psnr = 0.0f;
|
||||
m_bc7_luma_709_psnr = 0.0f;
|
||||
m_bc7_luma_601_psnr = 0.0f;
|
||||
m_bc7_luma_709_ssim = 0.0f;
|
||||
|
||||
m_best_etc1s_rgb_avg_psnr = 0.0f;
|
||||
m_best_etc1s_luma_709_psnr = 0.0f;
|
||||
m_best_etc1s_luma_601_psnr = 0.0f;
|
||||
m_best_etc1s_luma_709_ssim = 0.0f;
|
||||
}
|
||||
|
||||
std::string m_filename;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
// .basis compressed (ETC1S or UASTC statistics)
|
||||
float m_basis_rgb_avg_psnr;
|
||||
float m_basis_rgba_avg_psnr;
|
||||
float m_basis_a_avg_psnr;
|
||||
float m_basis_luma_709_psnr;
|
||||
float m_basis_luma_601_psnr;
|
||||
float m_basis_luma_709_ssim;
|
||||
|
||||
// BC7 statistics
|
||||
float m_bc7_rgb_avg_psnr;
|
||||
float m_bc7_rgba_avg_psnr;
|
||||
float m_bc7_a_avg_psnr;
|
||||
float m_bc7_luma_709_psnr;
|
||||
float m_bc7_luma_601_psnr;
|
||||
float m_bc7_luma_709_ssim;
|
||||
|
||||
// Highest achievable quality ETC1S statistics
|
||||
float m_best_etc1s_rgb_avg_psnr;
|
||||
float m_best_etc1s_luma_709_psnr;
|
||||
float m_best_etc1s_luma_601_psnr;
|
||||
float m_best_etc1s_luma_709_ssim;
|
||||
};
|
||||
|
||||
template<bool def>
|
||||
struct bool_param
|
||||
{
|
||||
bool_param() :
|
||||
m_value(def),
|
||||
m_changed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_value = def;
|
||||
m_changed = false;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool operator= (bool v)
|
||||
{
|
||||
m_value = v;
|
||||
m_changed = true;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool was_changed() const { return m_changed; }
|
||||
void set_changed(bool flag) { m_changed = flag; }
|
||||
|
||||
bool m_value;
|
||||
bool m_changed;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct param
|
||||
{
|
||||
param(T def, T min_v, T max_v) :
|
||||
m_value(def),
|
||||
m_def(def),
|
||||
m_min(min_v),
|
||||
m_max(max_v),
|
||||
m_changed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_value = m_def;
|
||||
m_changed = false;
|
||||
}
|
||||
|
||||
operator T() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
T operator= (T v)
|
||||
{
|
||||
m_value = clamp<T>(v, m_min, m_max);
|
||||
m_changed = true;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
T operator *= (T v)
|
||||
{
|
||||
m_value *= v;
|
||||
m_changed = true;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool was_changed() const { return m_changed; }
|
||||
void set_changed(bool flag) { m_changed = flag; }
|
||||
|
||||
T m_value;
|
||||
T m_def;
|
||||
T m_min;
|
||||
T m_max;
|
||||
bool m_changed;
|
||||
};
|
||||
|
||||
struct basis_compressor_params
|
||||
{
|
||||
basis_compressor_params() :
|
||||
m_compression_level((int)BASISU_DEFAULT_COMPRESSION_LEVEL, 0, (int)BASISU_MAX_COMPRESSION_LEVEL),
|
||||
m_selector_rdo_thresh(BASISU_DEFAULT_SELECTOR_RDO_THRESH, 0.0f, 1e+10f),
|
||||
m_endpoint_rdo_thresh(BASISU_DEFAULT_ENDPOINT_RDO_THRESH, 0.0f, 1e+10f),
|
||||
m_mip_scale(1.0f, .000125f, 4.0f),
|
||||
m_mip_smallest_dimension(1, 1, 16384),
|
||||
m_max_endpoint_clusters(512),
|
||||
m_max_selector_clusters(512),
|
||||
m_quality_level(-1),
|
||||
m_pack_uastc_flags(cPackUASTCLevelDefault),
|
||||
m_rdo_uastc_quality_scalar(1.0f, 0.001f, 50.0f),
|
||||
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_smooth_block_error_scale(UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE, 1.0f, 300.0f),
|
||||
m_rdo_uastc_smooth_block_max_std_dev(UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV, .01f, 65536.0f),
|
||||
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_resample_width(0, 1, 16384),
|
||||
m_resample_height(0, 1, 16384),
|
||||
m_resample_factor(0.0f, .00125f, 100.0f),
|
||||
m_ktx2_uastc_supercompression(basist::KTX2_SS_NONE),
|
||||
m_ktx2_zstd_supercompression_level(6, INT_MIN, INT_MAX),
|
||||
m_pJob_pool(nullptr)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_uastc.clear();
|
||||
m_use_opencl.clear();
|
||||
m_status_output.clear();
|
||||
|
||||
m_source_filenames.clear();
|
||||
m_source_alpha_filenames.clear();
|
||||
|
||||
m_source_images.clear();
|
||||
m_source_mipmap_images.clear();
|
||||
|
||||
m_out_filename.clear();
|
||||
|
||||
m_y_flip.clear();
|
||||
m_debug.clear();
|
||||
m_validate_etc1s.clear();
|
||||
m_debug_images.clear();
|
||||
m_perceptual.clear();
|
||||
m_no_selector_rdo.clear();
|
||||
m_selector_rdo_thresh.clear();
|
||||
m_read_source_images.clear();
|
||||
m_write_output_basis_files.clear();
|
||||
m_compression_level.clear();
|
||||
m_compute_stats.clear();
|
||||
m_check_for_alpha.clear();
|
||||
m_force_alpha.clear();
|
||||
m_multithreading.clear();
|
||||
m_swizzle[0] = 0;
|
||||
m_swizzle[1] = 1;
|
||||
m_swizzle[2] = 2;
|
||||
m_swizzle[3] = 3;
|
||||
m_renormalize.clear();
|
||||
m_disable_hierarchical_endpoint_codebooks.clear();
|
||||
|
||||
m_no_endpoint_rdo.clear();
|
||||
m_endpoint_rdo_thresh.clear();
|
||||
|
||||
m_mip_gen.clear();
|
||||
m_mip_scale.clear();
|
||||
m_mip_filter = "kaiser";
|
||||
m_mip_scale = 1.0f;
|
||||
m_mip_srgb.clear();
|
||||
m_mip_premultiplied.clear();
|
||||
m_mip_renormalize.clear();
|
||||
m_mip_wrapping.clear();
|
||||
m_mip_fast.clear();
|
||||
m_mip_smallest_dimension.clear();
|
||||
|
||||
m_max_endpoint_clusters = 0;
|
||||
m_max_selector_clusters = 0;
|
||||
m_quality_level = -1;
|
||||
|
||||
m_tex_type = basist::cBASISTexType2D;
|
||||
m_userdata0 = 0;
|
||||
m_userdata1 = 0;
|
||||
m_us_per_frame = 0;
|
||||
|
||||
m_pack_uastc_flags = cPackUASTCLevelDefault;
|
||||
m_rdo_uastc.clear();
|
||||
m_rdo_uastc_quality_scalar.clear();
|
||||
m_rdo_uastc_max_smooth_block_error_scale.clear();
|
||||
m_rdo_uastc_smooth_block_max_std_dev.clear();
|
||||
m_rdo_uastc_max_allowed_rms_increase_ratio.clear();
|
||||
m_rdo_uastc_skip_block_rms_thresh.clear();
|
||||
m_rdo_uastc_favor_simpler_modes_in_rdo_mode.clear();
|
||||
m_rdo_uastc_multithreading.clear();
|
||||
|
||||
m_resample_width.clear();
|
||||
m_resample_height.clear();
|
||||
m_resample_factor.clear();
|
||||
|
||||
m_pGlobal_codebooks = nullptr;
|
||||
|
||||
m_create_ktx2_file.clear();
|
||||
m_ktx2_uastc_supercompression = basist::KTX2_SS_NONE;
|
||||
m_ktx2_key_values.clear();
|
||||
m_ktx2_zstd_supercompression_level.clear();
|
||||
m_ktx2_srgb_transfer_func.clear();
|
||||
|
||||
m_validate_output_data.clear();
|
||||
|
||||
m_pJob_pool = nullptr;
|
||||
}
|
||||
|
||||
// True to generate UASTC .basis file data, otherwise ETC1S.
|
||||
bool_param<false> m_uastc;
|
||||
|
||||
bool_param<false> m_use_opencl;
|
||||
|
||||
// If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG images to read.
|
||||
// Otherwise, the compressor processes the images in m_source_images.
|
||||
basisu::vector<std::string> m_source_filenames;
|
||||
basisu::vector<std::string> m_source_alpha_filenames;
|
||||
|
||||
basisu::vector<image> m_source_images;
|
||||
|
||||
// Stores mipmaps starting from level 1. Level 0 is still stored in m_source_images, as usual.
|
||||
// If m_source_mipmaps isn't empty, automatic mipmap generation isn't done. m_source_mipmaps.size() MUST equal m_source_images.size() or the compressor returns an error.
|
||||
// The compressor applies the user-provided swizzling (in m_swizzle) to these images.
|
||||
basisu::vector< basisu::vector<image> > m_source_mipmap_images;
|
||||
|
||||
// Filename of the output basis file
|
||||
std::string m_out_filename;
|
||||
|
||||
// The params are done this way so we can detect when the user has explictly changed them.
|
||||
|
||||
// Flip images across Y axis
|
||||
bool_param<false> m_y_flip;
|
||||
|
||||
// If true, the compressor will print basis status to stdout during compression.
|
||||
bool_param<true> m_status_output;
|
||||
|
||||
// Output debug information during compression
|
||||
bool_param<false> m_debug;
|
||||
bool_param<false> m_validate_etc1s;
|
||||
|
||||
// m_debug_images is pretty slow
|
||||
bool_param<false> m_debug_images;
|
||||
|
||||
// ETC1S compression level, from 0 to BASISU_MAX_COMPRESSION_LEVEL (higher is slower).
|
||||
// This parameter controls numerous internal encoding speed vs. compression efficiency/performance tradeoffs.
|
||||
// Note this is NOT the same as the ETC1S quality level, and most users shouldn't change this.
|
||||
param<int> m_compression_level;
|
||||
|
||||
// Use perceptual sRGB colorspace metrics instead of linear
|
||||
bool_param<true> m_perceptual;
|
||||
|
||||
// Disable selector RDO, for faster compression but larger files
|
||||
bool_param<false> m_no_selector_rdo;
|
||||
param<float> m_selector_rdo_thresh;
|
||||
|
||||
bool_param<false> m_no_endpoint_rdo;
|
||||
param<float> m_endpoint_rdo_thresh;
|
||||
|
||||
// Read source images from m_source_filenames/m_source_alpha_filenames
|
||||
bool_param<false> m_read_source_images;
|
||||
|
||||
// Write the output basis file to disk using m_out_filename
|
||||
bool_param<false> m_write_output_basis_files;
|
||||
|
||||
// Compute and display image metrics
|
||||
bool_param<false> m_compute_stats;
|
||||
|
||||
// Check to see if any input image has an alpha channel, if so then the output basis file will have alpha channels
|
||||
bool_param<true> m_check_for_alpha;
|
||||
|
||||
// Always put alpha slices in the output basis file, even when the input doesn't have alpha
|
||||
bool_param<false> m_force_alpha;
|
||||
bool_param<true> m_multithreading;
|
||||
|
||||
// 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<false> m_renormalize;
|
||||
|
||||
// If true the front end will not use 2 level endpoint codebook searching, for slightly higher quality but much slower execution.
|
||||
// Note some m_compression_level's disable this automatically.
|
||||
bool_param<false> m_disable_hierarchical_endpoint_codebooks;
|
||||
|
||||
// mipmap generation parameters
|
||||
bool_param<false> m_mip_gen;
|
||||
param<float> m_mip_scale;
|
||||
std::string m_mip_filter;
|
||||
bool_param<false> m_mip_srgb;
|
||||
bool_param<true> m_mip_premultiplied; // not currently supported
|
||||
bool_param<false> m_mip_renormalize;
|
||||
bool_param<true> m_mip_wrapping;
|
||||
bool_param<true> m_mip_fast;
|
||||
param<int> m_mip_smallest_dimension;
|
||||
|
||||
// Codebook size (quality) control.
|
||||
// If m_quality_level != -1, it controls the quality level. It ranges from [1,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;
|
||||
int m_quality_level;
|
||||
|
||||
// m_tex_type, m_userdata0, m_userdata1, m_framerate - These fields go directly into the Basis file header.
|
||||
basist::basis_texture_type m_tex_type;
|
||||
uint32_t m_userdata0;
|
||||
uint32_t m_userdata1;
|
||||
uint32_t m_us_per_frame;
|
||||
|
||||
// cPackUASTCLevelDefault, etc.
|
||||
uint32_t m_pack_uastc_flags;
|
||||
bool_param<false> m_rdo_uastc;
|
||||
param<float> m_rdo_uastc_quality_scalar;
|
||||
param<int> m_rdo_uastc_dict_size;
|
||||
param<float> m_rdo_uastc_max_smooth_block_error_scale;
|
||||
param<float> m_rdo_uastc_smooth_block_max_std_dev;
|
||||
param<float> m_rdo_uastc_max_allowed_rms_increase_ratio;
|
||||
param<float> m_rdo_uastc_skip_block_rms_thresh;
|
||||
bool_param<true> m_rdo_uastc_favor_simpler_modes_in_rdo_mode;
|
||||
bool_param<true> m_rdo_uastc_multithreading;
|
||||
|
||||
param<int> m_resample_width;
|
||||
param<int> m_resample_height;
|
||||
param<float> m_resample_factor;
|
||||
|
||||
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
|
||||
|
||||
// KTX2 specific parameters.
|
||||
// Internally, the compressor always creates a .basis file then it converts that lossless to KTX2.
|
||||
bool_param<false> m_create_ktx2_file;
|
||||
basist::ktx2_supercompression m_ktx2_uastc_supercompression;
|
||||
basist::ktx2_transcoder::key_value_vec m_ktx2_key_values;
|
||||
param<int> m_ktx2_zstd_supercompression_level;
|
||||
bool_param<false> m_ktx2_srgb_transfer_func;
|
||||
|
||||
bool_param<false> m_validate_output_data;
|
||||
|
||||
job_pool *m_pJob_pool;
|
||||
};
|
||||
|
||||
// Important: basisu_encoder_init() MUST be called first before using this class.
|
||||
class basis_compressor
|
||||
{
|
||||
BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basis_compressor);
|
||||
|
||||
public:
|
||||
basis_compressor();
|
||||
~basis_compressor();
|
||||
|
||||
// Note it *should* be possible to call init() multiple times with different inputs, but this scenario isn't well tested. Ideally, create 1 object, compress, then delete it.
|
||||
bool init(const basis_compressor_params ¶ms);
|
||||
|
||||
enum error_code
|
||||
{
|
||||
cECSuccess = 0,
|
||||
cECFailedInitializing,
|
||||
cECFailedReadingSourceImages,
|
||||
cECFailedValidating,
|
||||
cECFailedEncodeUASTC,
|
||||
cECFailedFrontEnd,
|
||||
cECFailedFontendExtract,
|
||||
cECFailedBackend,
|
||||
cECFailedCreateBasisFile,
|
||||
cECFailedWritingOutput,
|
||||
cECFailedUASTCRDOPostProcess,
|
||||
cECFailedCreateKTX2File
|
||||
};
|
||||
|
||||
error_code process();
|
||||
|
||||
// The output .basis file will always be valid of process() succeeded.
|
||||
const uint8_vec &get_output_basis_file() const { return m_output_basis_file; }
|
||||
|
||||
// The output .ktx2 file will only be valid if m_create_ktx2_file was true and process() succeeded.
|
||||
const uint8_vec& get_output_ktx2_file() const { return m_output_ktx2_file; }
|
||||
|
||||
const basisu::vector<image_stats> &get_stats() const { return m_stats; }
|
||||
|
||||
uint32_t get_basis_file_size() const { return m_basis_file_size; }
|
||||
double get_basis_bits_per_texel() const { return m_basis_bits_per_texel; }
|
||||
|
||||
bool get_any_source_image_has_alpha() const { return m_any_source_image_has_alpha; }
|
||||
|
||||
bool get_opencl_failed() const { return m_opencl_failed; }
|
||||
|
||||
private:
|
||||
basis_compressor_params m_params;
|
||||
|
||||
opencl_context_ptr m_pOpenCL_context;
|
||||
|
||||
basisu::vector<image> m_slice_images;
|
||||
|
||||
basisu::vector<image_stats> m_stats;
|
||||
|
||||
uint32_t m_basis_file_size;
|
||||
double m_basis_bits_per_texel;
|
||||
|
||||
basisu_backend_slice_desc_vec m_slice_descs;
|
||||
|
||||
uint32_t m_total_blocks;
|
||||
|
||||
basisu_frontend m_frontend;
|
||||
pixel_block_vec m_source_blocks;
|
||||
|
||||
basisu::vector<gpu_image> m_frontend_output_textures;
|
||||
|
||||
basisu::vector<gpu_image> m_best_etc1s_images;
|
||||
basisu::vector<image> m_best_etc1s_images_unpacked;
|
||||
|
||||
basisu_backend m_backend;
|
||||
|
||||
basisu_file m_basis_file;
|
||||
|
||||
basisu::vector<gpu_image> m_decoded_output_textures;
|
||||
basisu::vector<image> m_decoded_output_textures_unpacked;
|
||||
basisu::vector<gpu_image> m_decoded_output_textures_bc7;
|
||||
basisu::vector<image> m_decoded_output_textures_unpacked_bc7;
|
||||
|
||||
uint8_vec m_output_basis_file;
|
||||
uint8_vec m_output_ktx2_file;
|
||||
|
||||
basisu::vector<gpu_image> m_uastc_slice_textures;
|
||||
basisu_backend_output m_uastc_backend_output;
|
||||
|
||||
bool m_any_source_image_has_alpha;
|
||||
|
||||
bool m_opencl_failed;
|
||||
|
||||
bool read_source_images();
|
||||
bool extract_source_blocks();
|
||||
bool process_frontend();
|
||||
bool extract_frontend_texture_data();
|
||||
bool process_backend();
|
||||
bool create_basis_file_and_transcode();
|
||||
bool write_output_files_and_compute_stats();
|
||||
error_code encode_slices_to_uastc();
|
||||
bool generate_mipmaps(const image &img, basisu::vector<image> &mips, bool has_alpha);
|
||||
bool validate_texture_type_constraints();
|
||||
bool validate_ktx2_constraints();
|
||||
void get_dfd(uint8_vec& dfd, const basist::ktx2_header& hdr);
|
||||
bool create_ktx2_file();
|
||||
};
|
||||
|
||||
// Alternative simple C-style wrapper API around the basis_compressor class.
|
||||
// This doesn't expose every encoder feature, but it's enough to get going.
|
||||
// Important: basisu_encoder_init() MUST be called first before calling these functions.
|
||||
//
|
||||
// Input parameters:
|
||||
// source_images: Array of "image" objects, one per mipmap level, largest mipmap level first.
|
||||
// OR
|
||||
// pImageRGBA: pointer to a 32-bpp RGBx or RGBA raster image, R first in memory, A last. Top scanline first in memory.
|
||||
// width/height/pitch_in_pixels: dimensions of pImageRGBA
|
||||
//
|
||||
// flags_and_quality: Combination of the above flags logically OR'd with the ETC1S or UASTC level, i.e. "cFlagSRGB | cFlagGenMipsClamp | cFlagThreaded | 128" or "cFlagSRGB | cFlagGenMipsClamp | cFlagUASTC | cFlagThreaded | cPackUASTCLevelDefault".
|
||||
// In ETC1S mode, the lower 8-bits are the ETC1S quality level which ranges from [1,255] (higher=better quality/larger files)
|
||||
// In UASTC mode, the lower 8-bits are the UASTC pack level (see cPackUASTCLevelFastest, etc.). Fastest/lowest quality is 0, so be sure to set it correctly.
|
||||
//
|
||||
// uastc_rdo_quality: Float UASTC RDO quality level (0=no change, higher values lower quality but increase compressibility, initially try .5-1.5)
|
||||
//
|
||||
// pSize: Returns the output data's compressed size in bytes
|
||||
//
|
||||
// Return value is the compressed .basis or .ktx2 file data, or nullptr on failure. Must call basis_free() to free it.
|
||||
enum
|
||||
{
|
||||
cFlagUseOpenCL = 1 << 8, // use OpenCL if available
|
||||
cFlagThreaded = 1 << 9, // use multiple threads for compression
|
||||
cFlagDebug = 1 << 10, // enable debug output
|
||||
|
||||
cFlagKTX2 = 1 << 11, // generate a KTX2 file
|
||||
cFlagKTX2UASTCSuperCompression = 1 << 12, // use KTX2 Zstd supercompression on UASTC files
|
||||
|
||||
cFlagSRGB = 1 << 13, // input texture is sRGB, use perceptual colorspace metrics, also use sRGB filtering during mipmap gen, and also sets KTX2 output transfer func to sRGB
|
||||
cFlagGenMipsClamp = 1 << 14, // generate mipmaps with clamp addressing
|
||||
cFlagGenMipsWrap = 1 << 15, // generate mipmaps with wrap addressing
|
||||
|
||||
cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
|
||||
|
||||
cFlagUASTC = 1 << 17, // use UASTC compression vs. ETC1S
|
||||
cFlagUASTCRDO = 1 << 18 // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
|
||||
};
|
||||
|
||||
// This function accepts an array of source images.
|
||||
// If more than one image is provided, it's assumed the images form a mipmap pyramid and automatic mipmap generation is disabled.
|
||||
void* basis_compress(
|
||||
const basisu::vector<image> &source_images,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
size_t* pSize,
|
||||
image_stats* pStats = nullptr);
|
||||
|
||||
// This function only accepts a single source image.
|
||||
void* basis_compress(
|
||||
const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
size_t* pSize,
|
||||
image_stats* pStats = nullptr);
|
||||
|
||||
// Frees the dynamically allocated file data returned by basis_compress().
|
||||
void basis_free_data(void* p);
|
||||
|
||||
// Parallel compression API
|
||||
struct parallel_results
|
||||
{
|
||||
double m_total_time;
|
||||
basis_compressor::error_code m_error_code;
|
||||
uint8_vec m_basis_file;
|
||||
uint8_vec m_ktx2_file;
|
||||
basisu::vector<image_stats> m_stats;
|
||||
double m_basis_bits_per_texel;
|
||||
bool m_any_source_image_has_alpha;
|
||||
|
||||
parallel_results()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_total_time = 0.0f;
|
||||
m_error_code = basis_compressor::cECFailedInitializing;
|
||||
m_basis_file.clear();
|
||||
m_ktx2_file.clear();
|
||||
m_stats.clear();
|
||||
m_basis_bits_per_texel = 0.0f;
|
||||
m_any_source_image_has_alpha = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Compresses an array of input textures across total_threads threads using the basis_compressor class.
|
||||
// Compressing multiple textures at a time is substantially more efficient than just compressing one at a time.
|
||||
// total_threads must be >= 1.
|
||||
bool basis_parallel_compress(
|
||||
uint32_t total_threads,
|
||||
const basisu::vector<basis_compressor_params> ¶ms_vec,
|
||||
basisu::vector< parallel_results > &results_vec);
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
+2116
File diff suppressed because it is too large
Load Diff
+3456
File diff suppressed because it is too large
Load Diff
+1610
File diff suppressed because it is too large
Load Diff
+1181
File diff suppressed because it is too large
Load Diff
+3458
File diff suppressed because it is too large
Load Diff
+353
@@ -0,0 +1,353 @@
|
||||
// basisu_frontend.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_etc.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include "../transcoder/basisu_file_headers.h"
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
struct opencl_context;
|
||||
typedef opencl_context* opencl_context_ptr;
|
||||
|
||||
struct vec2U
|
||||
{
|
||||
uint32_t m_comps[2];
|
||||
|
||||
vec2U() { }
|
||||
vec2U(uint32_t a, uint32_t b) { set(a, b); }
|
||||
|
||||
void set(uint32_t a, uint32_t b) { m_comps[0] = a; m_comps[1] = b; }
|
||||
|
||||
uint32_t operator[] (uint32_t i) const { assert(i < 2); return m_comps[i]; }
|
||||
uint32_t &operator[] (uint32_t i) { assert(i < 2); return m_comps[i]; }
|
||||
};
|
||||
|
||||
const uint32_t BASISU_DEFAULT_COMPRESSION_LEVEL = 2;
|
||||
const uint32_t BASISU_MAX_COMPRESSION_LEVEL = 6;
|
||||
|
||||
class basisu_frontend
|
||||
{
|
||||
BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_frontend);
|
||||
|
||||
public:
|
||||
|
||||
basisu_frontend() :
|
||||
m_total_blocks(0),
|
||||
m_total_pixels(0),
|
||||
m_endpoint_refinement(false),
|
||||
m_use_hierarchical_endpoint_codebooks(false),
|
||||
m_use_hierarchical_selector_codebooks(false),
|
||||
m_num_endpoint_codebook_iterations(0),
|
||||
m_num_selector_codebook_iterations(0),
|
||||
m_opencl_failed(false)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
cMaxEndpointClusters = 16128,
|
||||
|
||||
cMaxSelectorClusters = 16128,
|
||||
};
|
||||
|
||||
struct params
|
||||
{
|
||||
params() :
|
||||
m_num_source_blocks(0),
|
||||
m_pSource_blocks(NULL),
|
||||
m_max_endpoint_clusters(256),
|
||||
m_max_selector_clusters(256),
|
||||
m_compression_level(BASISU_DEFAULT_COMPRESSION_LEVEL),
|
||||
m_perceptual(true),
|
||||
m_debug_stats(false),
|
||||
m_debug_images(false),
|
||||
m_dump_endpoint_clusterization(true),
|
||||
m_validate(false),
|
||||
m_multithreaded(false),
|
||||
m_disable_hierarchical_endpoint_codebooks(false),
|
||||
m_tex_type(basist::cBASISTexType2D),
|
||||
m_pOpenCL_context(nullptr),
|
||||
m_pJob_pool(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t m_num_source_blocks;
|
||||
pixel_block *m_pSource_blocks;
|
||||
|
||||
uint32_t m_max_endpoint_clusters;
|
||||
uint32_t m_max_selector_clusters;
|
||||
|
||||
uint32_t m_compression_level;
|
||||
|
||||
bool m_perceptual;
|
||||
bool m_debug_stats;
|
||||
bool m_debug_images;
|
||||
bool m_dump_endpoint_clusterization;
|
||||
bool m_validate;
|
||||
bool m_multithreaded;
|
||||
bool m_disable_hierarchical_endpoint_codebooks;
|
||||
|
||||
basist::basis_texture_type m_tex_type;
|
||||
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
|
||||
|
||||
opencl_context_ptr m_pOpenCL_context;
|
||||
|
||||
job_pool *m_pJob_pool;
|
||||
};
|
||||
|
||||
bool init(const params &p);
|
||||
|
||||
bool compress();
|
||||
|
||||
const params &get_params() const { return m_params; }
|
||||
|
||||
const pixel_block &get_source_pixel_block(uint32_t i) const { return m_source_blocks[i]; }
|
||||
|
||||
// RDO output blocks
|
||||
uint32_t get_total_output_blocks() const { return static_cast<uint32_t>(m_encoded_blocks.size()); }
|
||||
|
||||
const etc_block &get_output_block(uint32_t block_index) const { return m_encoded_blocks[block_index]; }
|
||||
const etc_block_vec &get_output_blocks() const { return m_encoded_blocks; }
|
||||
|
||||
// "Best" ETC1S blocks
|
||||
const etc_block &get_etc1s_block(uint32_t block_index) const { return m_etc1_blocks_etc1s[block_index]; }
|
||||
|
||||
// Per-block flags
|
||||
bool get_diff_flag(uint32_t block_index) const { return m_encoded_blocks[block_index].get_diff_bit(); }
|
||||
|
||||
// Endpoint clusters
|
||||
uint32_t get_total_endpoint_clusters() const { return static_cast<uint32_t>(m_endpoint_clusters.size()); }
|
||||
uint32_t get_subblock_endpoint_cluster_index(uint32_t block_index, uint32_t subblock_index) const { return m_block_endpoint_clusters_indices[block_index][subblock_index]; }
|
||||
|
||||
const color_rgba &get_endpoint_cluster_unscaled_color(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_color_unscaled[individual_mode]; }
|
||||
uint32_t get_endpoint_cluster_inten_table(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_inten_table[individual_mode]; }
|
||||
|
||||
bool get_endpoint_cluster_color_is_used(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_color_used[individual_mode]; }
|
||||
|
||||
// Selector clusters
|
||||
uint32_t get_total_selector_clusters() const { return static_cast<uint32_t>(m_selector_cluster_block_indices.size()); }
|
||||
uint32_t get_block_selector_cluster_index(uint32_t block_index) const { return m_block_selector_cluster_index[block_index]; }
|
||||
const etc_block &get_selector_cluster_selector_bits(uint32_t cluster_index) const { return m_optimized_cluster_selectors[cluster_index]; }
|
||||
|
||||
// Returns block indices using each selector cluster
|
||||
const uint_vec &get_selector_cluster_block_indices(uint32_t selector_cluster_index) const { return m_selector_cluster_block_indices[selector_cluster_index]; }
|
||||
|
||||
void dump_debug_image(const char *pFilename, uint32_t first_block, uint32_t num_blocks_x, uint32_t num_blocks_y, bool output_blocks);
|
||||
|
||||
void reoptimize_remapped_endpoints(const uint_vec &new_block_endpoints, int_vec &old_to_new_endpoint_cluster_indices, bool optimize_final_codebook, uint_vec *pBlock_selector_indices = nullptr);
|
||||
|
||||
bool get_opencl_failed() const { return m_opencl_failed; }
|
||||
|
||||
private:
|
||||
params m_params;
|
||||
uint32_t m_total_blocks;
|
||||
uint32_t m_total_pixels;
|
||||
|
||||
bool m_endpoint_refinement;
|
||||
bool m_use_hierarchical_endpoint_codebooks;
|
||||
bool m_use_hierarchical_selector_codebooks;
|
||||
|
||||
uint32_t m_num_endpoint_codebook_iterations;
|
||||
uint32_t m_num_selector_codebook_iterations;
|
||||
|
||||
// Source pixels for each blocks
|
||||
pixel_block_vec m_source_blocks;
|
||||
|
||||
// The quantized ETC1S texture.
|
||||
etc_block_vec m_encoded_blocks;
|
||||
|
||||
// Quantized blocks after endpoint quant, but before selector quant
|
||||
etc_block_vec m_orig_encoded_blocks;
|
||||
|
||||
// Full quality ETC1S texture
|
||||
etc_block_vec m_etc1_blocks_etc1s;
|
||||
|
||||
typedef vec<6, float> vec6F;
|
||||
|
||||
// Endpoint clusterizer
|
||||
typedef tree_vector_quant<vec6F> vec6F_quantizer;
|
||||
vec6F_quantizer m_endpoint_clusterizer;
|
||||
|
||||
// For each endpoint cluster: An array of which subblock indices (block_index*2+subblock) are located in that cluster.
|
||||
basisu::vector<uint_vec> m_endpoint_clusters;
|
||||
|
||||
// Array of subblock indices for each parent endpoint cluster
|
||||
// Note: Initially, each endpoint cluster will only live in a single parent cluster, in a shallow tree.
|
||||
// As the endpoint clusters are manipulated this constraint gets broken.
|
||||
basisu::vector<uint_vec> m_endpoint_parent_clusters;
|
||||
|
||||
// Each block's parent endpoint cluster index
|
||||
uint8_vec m_block_parent_endpoint_cluster;
|
||||
|
||||
// Array of endpoint cluster indices for each parent endpoint cluster
|
||||
basisu::vector<uint_vec> m_endpoint_clusters_within_each_parent_cluster;
|
||||
|
||||
struct endpoint_cluster_etc_params
|
||||
{
|
||||
endpoint_cluster_etc_params()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
clear_obj(m_color_unscaled);
|
||||
clear_obj(m_inten_table);
|
||||
clear_obj(m_color_error);
|
||||
m_subblocks.clear();
|
||||
|
||||
clear_obj(m_color_used);
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
// TODO: basisu doesn't use individual mode.
|
||||
color_rgba m_color_unscaled[2]; // [use_individual_mode]
|
||||
uint32_t m_inten_table[2];
|
||||
|
||||
uint64_t m_color_error[2];
|
||||
|
||||
uint_vec m_subblocks;
|
||||
|
||||
bool m_color_used[2];
|
||||
|
||||
bool m_valid;
|
||||
|
||||
bool operator== (const endpoint_cluster_etc_params &other) const
|
||||
{
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_color_unscaled[i] != other.m_color_unscaled[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_inten_table[0] != other.m_inten_table[0])
|
||||
return false;
|
||||
if (m_inten_table[1] != other.m_inten_table[1])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator< (const endpoint_cluster_etc_params &other) const
|
||||
{
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_color_unscaled[i] < other.m_color_unscaled[i])
|
||||
return true;
|
||||
else if (m_color_unscaled[i] != other.m_color_unscaled[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_inten_table[0] < other.m_inten_table[0])
|
||||
return true;
|
||||
else if (m_inten_table[0] == other.m_inten_table[0])
|
||||
{
|
||||
if (m_inten_table[1] < other.m_inten_table[1])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef basisu::vector<endpoint_cluster_etc_params> cluster_subblock_etc_params_vec;
|
||||
|
||||
// Each endpoint cluster's ETC1S parameters
|
||||
cluster_subblock_etc_params_vec m_endpoint_cluster_etc_params;
|
||||
|
||||
// The endpoint cluster index used by each ETC1 subblock.
|
||||
basisu::vector<vec2U> m_block_endpoint_clusters_indices;
|
||||
|
||||
// The block(s) within each selector cluster
|
||||
// Note: If you add anything here that uses selector cluster indicies, be sure to update optimize_selector_codebook()!
|
||||
basisu::vector<uint_vec> m_selector_cluster_block_indices;
|
||||
|
||||
// The selector bits for each selector cluster.
|
||||
basisu::vector<etc_block> m_optimized_cluster_selectors;
|
||||
|
||||
// The block(s) within each parent selector cluster.
|
||||
basisu::vector<uint_vec> m_selector_parent_cluster_block_indices;
|
||||
|
||||
// Each block's parent selector cluster
|
||||
uint8_vec m_block_parent_selector_cluster;
|
||||
|
||||
// Array of selector cluster indices for each parent selector cluster
|
||||
basisu::vector<uint_vec> m_selector_clusters_within_each_parent_cluster;
|
||||
|
||||
// Each block's selector cluster index
|
||||
basisu::vector<uint32_t> m_block_selector_cluster_index;
|
||||
|
||||
struct subblock_endpoint_quant_err
|
||||
{
|
||||
uint64_t m_total_err;
|
||||
uint32_t m_cluster_index;
|
||||
uint32_t m_cluster_subblock_index;
|
||||
uint32_t m_block_index;
|
||||
uint32_t m_subblock_index;
|
||||
|
||||
bool operator< (const subblock_endpoint_quant_err &rhs) const
|
||||
{
|
||||
if (m_total_err < rhs.m_total_err)
|
||||
return true;
|
||||
else if (m_total_err == rhs.m_total_err)
|
||||
{
|
||||
if (m_block_index < rhs.m_block_index)
|
||||
return true;
|
||||
else if (m_block_index == rhs.m_block_index)
|
||||
return m_subblock_index < rhs.m_subblock_index;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// The sorted subblock endpoint quant error for each endpoint cluster
|
||||
basisu::vector<subblock_endpoint_quant_err> m_subblock_endpoint_quant_err_vec;
|
||||
|
||||
std::mutex m_lock;
|
||||
|
||||
bool m_opencl_failed;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void init_etc1_images();
|
||||
bool init_global_codebooks();
|
||||
void init_endpoint_training_vectors();
|
||||
void dump_endpoint_clusterization_visualization(const char *pFilename, bool vis_endpoint_colors);
|
||||
void generate_endpoint_clusters();
|
||||
void compute_endpoint_subblock_error_vec();
|
||||
void introduce_new_endpoint_clusters();
|
||||
void generate_endpoint_codebook(uint32_t step);
|
||||
uint32_t refine_endpoint_clusterization();
|
||||
void eliminate_redundant_or_empty_endpoint_clusters();
|
||||
void generate_block_endpoint_clusters();
|
||||
void compute_endpoint_clusters_within_each_parent_cluster();
|
||||
void compute_selector_clusters_within_each_parent_cluster();
|
||||
void create_initial_packed_texture();
|
||||
void generate_selector_clusters();
|
||||
void create_optimized_selector_codebook(uint32_t iter);
|
||||
void find_optimal_selector_clusters_for_each_block();
|
||||
uint32_t refine_block_endpoints_given_selectors();
|
||||
void finalize();
|
||||
bool validate_endpoint_cluster_hierarchy(bool ensure_clusters_have_same_parents) const;
|
||||
bool validate_output() const;
|
||||
void introduce_special_selector_clusters();
|
||||
void optimize_selector_codebook();
|
||||
bool check_etc1s_constraints() const;
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
+1626
File diff suppressed because it is too large
Load Diff
+154
@@ -0,0 +1,154 @@
|
||||
// basisu_gpu_texture.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "../transcoder/basisu.h"
|
||||
#include "basisu_etc.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
// GPU texture "image"
|
||||
class gpu_image
|
||||
{
|
||||
public:
|
||||
enum { cMaxBlockSize = 12 };
|
||||
|
||||
gpu_image()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
gpu_image(texture_format fmt, uint32_t width, uint32_t height)
|
||||
{
|
||||
init(fmt, width, height);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_fmt = texture_format::cInvalidTextureFormat;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_block_width = 0;
|
||||
m_block_height = 0;
|
||||
m_blocks_x = 0;
|
||||
m_blocks_y = 0;
|
||||
m_qwords_per_block = 0;
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
inline texture_format get_format() const { return m_fmt; }
|
||||
|
||||
// Width/height in pixels
|
||||
inline uint32_t get_pixel_width() const { return m_width; }
|
||||
inline uint32_t get_pixel_height() const { return m_height; }
|
||||
|
||||
// Width/height in blocks, row pitch is assumed to be m_blocks_x.
|
||||
inline uint32_t get_blocks_x() const { return m_blocks_x; }
|
||||
inline uint32_t get_blocks_y() const { return m_blocks_y; }
|
||||
|
||||
// Size of each block in pixels
|
||||
inline uint32_t get_block_width() const { return m_block_width; }
|
||||
inline uint32_t get_block_height() const { return m_block_height; }
|
||||
|
||||
inline uint32_t get_qwords_per_block() const { return m_qwords_per_block; }
|
||||
inline uint32_t get_total_blocks() const { return m_blocks_x * m_blocks_y; }
|
||||
inline uint32_t get_bytes_per_block() const { return get_qwords_per_block() * sizeof(uint64_t); }
|
||||
inline uint32_t get_row_pitch_in_bytes() const { return get_bytes_per_block() * get_blocks_x(); }
|
||||
|
||||
inline const uint64_vec &get_blocks() const { return m_blocks; }
|
||||
|
||||
inline const uint64_t *get_ptr() const { return &m_blocks[0]; }
|
||||
inline uint64_t *get_ptr() { return &m_blocks[0]; }
|
||||
|
||||
inline uint32_t get_size_in_bytes() const { return get_total_blocks() * get_qwords_per_block() * sizeof(uint64_t); }
|
||||
|
||||
inline const void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0) const
|
||||
{
|
||||
assert(block_x < m_blocks_x && block_y < m_blocks_y);
|
||||
return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
|
||||
}
|
||||
|
||||
inline void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0)
|
||||
{
|
||||
assert(block_x < m_blocks_x && block_y < m_blocks_y && element_index < m_qwords_per_block);
|
||||
return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
|
||||
}
|
||||
|
||||
void init(texture_format fmt, uint32_t width, uint32_t height)
|
||||
{
|
||||
m_fmt = fmt;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_block_width = basisu::get_block_width(m_fmt);
|
||||
m_block_height = basisu::get_block_height(m_fmt);
|
||||
m_blocks_x = (m_width + m_block_width - 1) / m_block_width;
|
||||
m_blocks_y = (m_height + m_block_height - 1) / m_block_height;
|
||||
m_qwords_per_block = basisu::get_qwords_per_block(m_fmt);
|
||||
|
||||
m_blocks.resize(0);
|
||||
m_blocks.resize(m_blocks_x * m_blocks_y * m_qwords_per_block);
|
||||
}
|
||||
|
||||
bool unpack(image& img) const;
|
||||
|
||||
void override_dimensions(uint32_t w, uint32_t h)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
}
|
||||
|
||||
private:
|
||||
texture_format m_fmt;
|
||||
uint32_t m_width, m_height, m_blocks_x, m_blocks_y, m_block_width, m_block_height, m_qwords_per_block;
|
||||
uint64_vec m_blocks;
|
||||
};
|
||||
|
||||
typedef basisu::vector<gpu_image> gpu_image_vec;
|
||||
|
||||
// KTX file writing
|
||||
|
||||
bool create_ktx_texture_file(uint8_vec &ktx_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag);
|
||||
|
||||
bool write_compressed_texture_file(const char *pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag);
|
||||
|
||||
inline bool write_compressed_texture_file(const char *pFilename, const gpu_image_vec &g)
|
||||
{
|
||||
basisu::vector<gpu_image_vec> a;
|
||||
a.push_back(g);
|
||||
return write_compressed_texture_file(pFilename, a, false);
|
||||
}
|
||||
|
||||
bool write_compressed_texture_file(const char *pFilename, const gpu_image &g);
|
||||
|
||||
bool write_3dfx_out_file(const char* pFilename, const gpu_image& gi);
|
||||
|
||||
// GPU texture block unpacking
|
||||
void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc1(const void *pBlock_bits, color_rgba *pPixels, bool set_alpha);
|
||||
void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride);
|
||||
bool unpack_bc3(const void *pBlock_bits, color_rgba *pPixels);
|
||||
void unpack_bc5(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc7(const void* pBlock_bits, color_rgba* pPixels);
|
||||
void unpack_atc(const void* pBlock_bits, color_rgba* pPixels);
|
||||
bool unpack_fxt1(const void* p, color_rgba* pPixels);
|
||||
bool unpack_pvrtc2(const void* p, color_rgba* pPixels);
|
||||
void unpack_etc2_eac_r(const void *p, color_rgba* pPixels, uint32_t c);
|
||||
void unpack_etc2_eac_rg(const void* p, color_rgba* pPixels);
|
||||
|
||||
// unpack_block() is primarily intended to unpack texture data created by the transcoder.
|
||||
// For some texture formats (like ETC2 RGB, PVRTC2, FXT1) it's not a complete implementation.
|
||||
bool unpack_block(texture_format fmt, const void *pBlock, color_rgba *pPixels);
|
||||
|
||||
} // namespace basisu
|
||||
@@ -0,0 +1,27 @@
|
||||
// basisu_kernels_declares.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#if BASISU_SUPPORT_SSE
|
||||
void CPPSPMD_NAME(perceptual_distance_rgb_4_N)(int64_t* pDistance, const uint8_t* pSelectors, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err);
|
||||
void CPPSPMD_NAME(linear_distance_rgb_4_N)(int64_t* pDistance, const uint8_t* pSelectors, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err);
|
||||
|
||||
void CPPSPMD_NAME(find_selectors_perceptual_rgb_4_N)(int64_t* pDistance, uint8_t* pSelectors, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err);
|
||||
void CPPSPMD_NAME(find_selectors_linear_rgb_4_N)(int64_t* pDistance, uint8_t* pSelectors, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err);
|
||||
|
||||
void CPPSPMD_NAME(find_lowest_error_perceptual_rgb_4_N)(int64_t* pDistance, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error);
|
||||
void CPPSPMD_NAME(find_lowest_error_linear_rgb_4_N)(int64_t* pDistance, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error);
|
||||
|
||||
void CPPSPMD_NAME(update_covar_matrix_16x16)(uint32_t num_vecs, const void* pWeighted_vecs, const void *pOrigin, const uint32_t* pVec_indices, void *pMatrix16x16);
|
||||
#endif
|
||||
+647
@@ -0,0 +1,647 @@
|
||||
// basisu_kernels_imp.h - Do not directly include
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using namespace CPPSPMD;
|
||||
|
||||
namespace CPPSPMD_NAME(basisu_kernels_namespace)
|
||||
{
|
||||
struct perceptual_distance_rgb_4_N : spmd_kernel
|
||||
{
|
||||
void _call(int64_t* pDistance,
|
||||
const uint8_t* pSelectors,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_err)
|
||||
{
|
||||
assert(early_out_err >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
__m128i block_colors[4];
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
block_colors[i] = load_rgba32(&pBlock_colors[i]);
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
int s0 = pSelectors[i], s1 = pSelectors[i + 1], s2 = pSelectors[i + 2], s3 = pSelectors[i + 3];
|
||||
|
||||
vint base_r, base_g, base_b, base_a;
|
||||
if ((s0 == s1) && (s0 == s2) && (s0 == s3))
|
||||
{
|
||||
store_all(base_r, block_colors_r[s0]);
|
||||
store_all(base_g, block_colors_g[s0]);
|
||||
store_all(base_b, block_colors_b[s0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
__m128i k0 = block_colors[s0], k1 = block_colors[s1], k2 = block_colors[s2], k3 = block_colors[s3];
|
||||
transpose4x4(base_r.m_value, base_g.m_value, base_b.m_value, base_a.m_value, k0, k1, k2, k3);
|
||||
}
|
||||
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
vint delta_cr = dr * 128 - delta_l;
|
||||
vint delta_cb = db * 128 - delta_l;
|
||||
|
||||
vint id = ((delta_l * delta_l) >> 7) +
|
||||
((((delta_cr * delta_cr) >> 7) * 26) >> 7) +
|
||||
((((delta_cb * delta_cb) >> 7) * 3) >> 7);
|
||||
|
||||
*pDistance += reduce_add(id);
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int sel = pSelectors[i];
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
int delta_cr = dr * 128 - delta_l;
|
||||
int delta_cb = db * 128 - delta_l;
|
||||
|
||||
int id = ((delta_l * delta_l) >> 7) +
|
||||
((((delta_cr * delta_cr) >> 7) * 26) >> 7) +
|
||||
((((delta_cb * delta_cb) >> 7) * 3) >> 7);
|
||||
|
||||
*pDistance += id;
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct linear_distance_rgb_4_N : spmd_kernel
|
||||
{
|
||||
void _call(int64_t* pDistance,
|
||||
const uint8_t* pSelectors,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_err)
|
||||
{
|
||||
assert(early_out_err >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
__m128i block_colors[4];
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
block_colors[i] = load_rgba32(&pBlock_colors[i]);
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
int s0 = pSelectors[i], s1 = pSelectors[i + 1], s2 = pSelectors[i + 2], s3 = pSelectors[i + 3];
|
||||
|
||||
vint base_r, base_g, base_b, base_a;
|
||||
if ((s0 == s1) && (s0 == s2) && (s0 == s3))
|
||||
{
|
||||
store_all(base_r, block_colors_r[s0]);
|
||||
store_all(base_g, block_colors_g[s0]);
|
||||
store_all(base_b, block_colors_b[s0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
__m128i k0 = block_colors[s0], k1 = block_colors[s1], k2 = block_colors[s2], k3 = block_colors[s3];
|
||||
transpose4x4(base_r.m_value, base_g.m_value, base_b.m_value, base_a.m_value, k0, k1, k2, k3);
|
||||
}
|
||||
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint id = dr * dr + dg * dg + db * db;
|
||||
|
||||
*pDistance += reduce_add(id);
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int sel = pSelectors[i];
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int id = dr * dr + dg * dg + db * db;
|
||||
|
||||
*pDistance += id;
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct find_selectors_perceptual_rgb_4_N : spmd_kernel
|
||||
{
|
||||
inline vint compute_dist(
|
||||
const vint& base_r, const vint& base_g, const vint& base_b,
|
||||
const vint& r, const vint& g, const vint& b)
|
||||
{
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
vint delta_cr = dr * 128 - delta_l;
|
||||
vint delta_cb = db * 128 - delta_l;
|
||||
|
||||
vint id = VINT_SHIFT_RIGHT(delta_l * delta_l, 7) +
|
||||
VINT_SHIFT_RIGHT(VINT_SHIFT_RIGHT(delta_cr * delta_cr, 7) * 26, 7) +
|
||||
VINT_SHIFT_RIGHT(VINT_SHIFT_RIGHT(delta_cb * delta_cb, 7) * 3, 7);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void _call(int64_t* pDistance,
|
||||
uint8_t* pSelectors,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_err)
|
||||
{
|
||||
assert(early_out_err >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
const __m128i shuf = _mm_set_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, 12, 8, 4, 0);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
vint dist0 = compute_dist(block_colors_r[0], block_colors_g[0], block_colors_b[0], r, g, b);
|
||||
vint dist1 = compute_dist(block_colors_r[1], block_colors_g[1], block_colors_b[1], r, g, b);
|
||||
vint dist2 = compute_dist(block_colors_r[2], block_colors_g[2], block_colors_b[2], r, g, b);
|
||||
vint dist3 = compute_dist(block_colors_r[3], block_colors_g[3], block_colors_b[3], r, g, b);
|
||||
|
||||
vint min_dist = min(min(min(dist0, dist1), dist2), dist3);
|
||||
|
||||
vint sels = spmd_ternaryi(min_dist == dist0, 0, spmd_ternaryi(min_dist == dist1, 1, spmd_ternaryi(min_dist == dist2, 2, 3)));
|
||||
|
||||
__m128i vsels = shuffle_epi8(sels.m_value, shuf);
|
||||
storeu_si32((void *)(pSelectors + i), vsels);
|
||||
|
||||
*pDistance += reduce_add(min_dist);
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int best_err = INT_MAX, best_sel = 0;
|
||||
for (int sel = 0; sel < 4; sel++)
|
||||
{
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
int delta_cr = dr * 128 - delta_l;
|
||||
int delta_cb = db * 128 - delta_l;
|
||||
|
||||
int id = ((delta_l * delta_l) >> 7) +
|
||||
((((delta_cr * delta_cr) >> 7) * 26) >> 7) +
|
||||
((((delta_cb * delta_cb) >> 7) * 3) >> 7);
|
||||
if (id < best_err)
|
||||
{
|
||||
best_err = id;
|
||||
best_sel = sel;
|
||||
}
|
||||
}
|
||||
|
||||
pSelectors[i] = (uint8_t)best_sel;
|
||||
|
||||
*pDistance += best_err;
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct find_selectors_linear_rgb_4_N : spmd_kernel
|
||||
{
|
||||
inline vint compute_dist(
|
||||
const vint& base_r, const vint& base_g, const vint& base_b,
|
||||
const vint& r, const vint& g, const vint& b)
|
||||
{
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint id = dr * dr + dg * dg + db * db;
|
||||
return id;
|
||||
}
|
||||
|
||||
void _call(int64_t* pDistance,
|
||||
uint8_t* pSelectors,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_err)
|
||||
{
|
||||
assert(early_out_err >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
const __m128i shuf = _mm_set_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, 12, 8, 4, 0);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
vint dist0 = compute_dist(block_colors_r[0], block_colors_g[0], block_colors_b[0], r, g, b);
|
||||
vint dist1 = compute_dist(block_colors_r[1], block_colors_g[1], block_colors_b[1], r, g, b);
|
||||
vint dist2 = compute_dist(block_colors_r[2], block_colors_g[2], block_colors_b[2], r, g, b);
|
||||
vint dist3 = compute_dist(block_colors_r[3], block_colors_g[3], block_colors_b[3], r, g, b);
|
||||
|
||||
vint min_dist = min(min(min(dist0, dist1), dist2), dist3);
|
||||
|
||||
vint sels = spmd_ternaryi(min_dist == dist0, 0, spmd_ternaryi(min_dist == dist1, 1, spmd_ternaryi(min_dist == dist2, 2, 3)));
|
||||
|
||||
__m128i vsels = shuffle_epi8(sels.m_value, shuf);
|
||||
storeu_si32((void *)(pSelectors + i), vsels);
|
||||
|
||||
*pDistance += reduce_add(min_dist);
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int best_err = INT_MAX, best_sel = 0;
|
||||
for (int sel = 0; sel < 4; sel++)
|
||||
{
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int id = dr * dr + dg * dg + db * db;
|
||||
if (id < best_err)
|
||||
{
|
||||
best_err = id;
|
||||
best_sel = sel;
|
||||
}
|
||||
}
|
||||
|
||||
pSelectors[i] = (uint8_t)best_sel;
|
||||
|
||||
*pDistance += best_err;
|
||||
if (*pDistance >= early_out_err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct find_lowest_error_perceptual_rgb_4_N : spmd_kernel
|
||||
{
|
||||
inline vint compute_dist(
|
||||
const vint& base_r, const vint& base_g, const vint& base_b,
|
||||
const vint& r, const vint& g, const vint& b)
|
||||
{
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
vint delta_cr = dr * 128 - delta_l;
|
||||
vint delta_cb = db * 128 - delta_l;
|
||||
|
||||
vint id = VINT_SHIFT_RIGHT(delta_l * delta_l, 7) +
|
||||
VINT_SHIFT_RIGHT(VINT_SHIFT_RIGHT(delta_cr * delta_cr, 7) * 26, 7) +
|
||||
VINT_SHIFT_RIGHT(VINT_SHIFT_RIGHT(delta_cb * delta_cb, 7) * 3, 7);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void _call(int64_t* pDistance,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_error)
|
||||
{
|
||||
assert(early_out_error >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
vint dist0 = compute_dist(block_colors_r[0], block_colors_g[0], block_colors_b[0], r, g, b);
|
||||
vint dist1 = compute_dist(block_colors_r[1], block_colors_g[1], block_colors_b[1], r, g, b);
|
||||
vint dist2 = compute_dist(block_colors_r[2], block_colors_g[2], block_colors_b[2], r, g, b);
|
||||
vint dist3 = compute_dist(block_colors_r[3], block_colors_g[3], block_colors_b[3], r, g, b);
|
||||
|
||||
vint min_dist = min(min(min(dist0, dist1), dist2), dist3);
|
||||
|
||||
*pDistance += reduce_add(min_dist);
|
||||
if (*pDistance > early_out_error)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int best_err = INT_MAX;
|
||||
for (int sel = 0; sel < 4; sel++)
|
||||
{
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int delta_l = dr * 27 + dg * 92 + db * 9;
|
||||
int delta_cr = dr * 128 - delta_l;
|
||||
int delta_cb = db * 128 - delta_l;
|
||||
|
||||
int id = ((delta_l * delta_l) >> 7) +
|
||||
((((delta_cr * delta_cr) >> 7) * 26) >> 7) +
|
||||
((((delta_cb * delta_cb) >> 7) * 3) >> 7);
|
||||
|
||||
if (id < best_err)
|
||||
{
|
||||
best_err = id;
|
||||
}
|
||||
}
|
||||
|
||||
*pDistance += best_err;
|
||||
if (*pDistance > early_out_error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct find_lowest_error_linear_rgb_4_N : spmd_kernel
|
||||
{
|
||||
inline vint compute_dist(
|
||||
const vint& base_r, const vint& base_g, const vint& base_b,
|
||||
const vint& r, const vint& g, const vint& b)
|
||||
{
|
||||
vint dr = base_r - r;
|
||||
vint dg = base_g - g;
|
||||
vint db = base_b - b;
|
||||
|
||||
vint id = dr * dr + dg * dg + db * db;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void _call(int64_t* pDistance,
|
||||
const color_rgba* pBlock_colors,
|
||||
const color_rgba* pSrc_pixels, uint32_t n,
|
||||
int64_t early_out_error)
|
||||
{
|
||||
assert(early_out_error >= 0);
|
||||
|
||||
*pDistance = 0;
|
||||
|
||||
vint block_colors_r[4], block_colors_g[4], block_colors_b[4];
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
store_all(block_colors_r[i], (int)pBlock_colors[i].r);
|
||||
store_all(block_colors_g[i], (int)pBlock_colors[i].g);
|
||||
store_all(block_colors_b[i], (int)pBlock_colors[i].b);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; (i + 4) <= n; i += 4)
|
||||
{
|
||||
__m128i c0 = load_rgba32(&pSrc_pixels[i + 0]), c1 = load_rgba32(&pSrc_pixels[i + 1]), c2 = load_rgba32(&pSrc_pixels[i + 2]), c3 = load_rgba32(&pSrc_pixels[i + 3]);
|
||||
|
||||
vint r, g, b, a;
|
||||
transpose4x4(r.m_value, g.m_value, b.m_value, a.m_value, c0, c1, c2, c3);
|
||||
|
||||
vint dist0 = compute_dist(block_colors_r[0], block_colors_g[0], block_colors_b[0], r, g, b);
|
||||
vint dist1 = compute_dist(block_colors_r[1], block_colors_g[1], block_colors_b[1], r, g, b);
|
||||
vint dist2 = compute_dist(block_colors_r[2], block_colors_g[2], block_colors_b[2], r, g, b);
|
||||
vint dist3 = compute_dist(block_colors_r[3], block_colors_g[3], block_colors_b[3], r, g, b);
|
||||
|
||||
vint min_dist = min(min(min(dist0, dist1), dist2), dist3);
|
||||
|
||||
*pDistance += reduce_add(min_dist);
|
||||
if (*pDistance > early_out_error)
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
{
|
||||
int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
|
||||
|
||||
int best_err = INT_MAX;
|
||||
for (int sel = 0; sel < 4; sel++)
|
||||
{
|
||||
int base_r = pBlock_colors[sel].r, base_g = pBlock_colors[sel].g, base_b = pBlock_colors[sel].b;
|
||||
|
||||
int dr = base_r - r;
|
||||
int dg = base_g - g;
|
||||
int db = base_b - b;
|
||||
|
||||
int id = dr * dr + dg * dg + db * db;
|
||||
|
||||
if (id < best_err)
|
||||
{
|
||||
best_err = id;
|
||||
}
|
||||
}
|
||||
|
||||
*pDistance += best_err;
|
||||
if (*pDistance > early_out_error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct update_covar_matrix_16x16 : spmd_kernel
|
||||
{
|
||||
void _call(
|
||||
uint32_t num_vecs, const void* pWeighted_vecs_void, const void* pOrigin_void, const uint32_t* pVec_indices, void* pMatrix16x16_void)
|
||||
{
|
||||
const std::pair<vec16F, uint64_t>* pWeighted_vecs = static_cast< const std::pair<vec16F, uint64_t> *>(pWeighted_vecs_void);
|
||||
|
||||
const float* pOrigin = static_cast<const float*>(pOrigin_void);
|
||||
vfloat org0 = loadu_linear_all(pOrigin), org1 = loadu_linear_all(pOrigin + 4), org2 = loadu_linear_all(pOrigin + 8), org3 = loadu_linear_all(pOrigin + 12);
|
||||
|
||||
vfloat mat[16][4];
|
||||
vfloat vzero(zero_vfloat());
|
||||
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
store_all(mat[i][0], vzero);
|
||||
store_all(mat[i][1], vzero);
|
||||
store_all(mat[i][2], vzero);
|
||||
store_all(mat[i][3], vzero);
|
||||
}
|
||||
|
||||
for (uint32_t k = 0; k < num_vecs; k++)
|
||||
{
|
||||
const uint32_t vec_index = pVec_indices[k];
|
||||
|
||||
const float* pW = pWeighted_vecs[vec_index].first.get_ptr();
|
||||
vfloat weight((float)pWeighted_vecs[vec_index].second);
|
||||
|
||||
vfloat vec[4] = { loadu_linear_all(pW) - org0, loadu_linear_all(pW + 4) - org1, loadu_linear_all(pW + 8) - org2, loadu_linear_all(pW + 12) - org3 };
|
||||
|
||||
vfloat wvec0 = vec[0] * weight, wvec1 = vec[1] * weight, wvec2 = vec[2] * weight, wvec3 = vec[3] * weight;
|
||||
|
||||
for (uint32_t j = 0; j < 16; j++)
|
||||
{
|
||||
vfloat vx = ((const float*)vec)[j];
|
||||
|
||||
store_all(mat[j][0], mat[j][0] + vx * wvec0);
|
||||
store_all(mat[j][1], mat[j][1] + vx * wvec1);
|
||||
store_all(mat[j][2], mat[j][2] + vx * wvec2);
|
||||
store_all(mat[j][3], mat[j][3] + vx * wvec3);
|
||||
|
||||
} // j
|
||||
|
||||
} // k
|
||||
|
||||
float* pMatrix = static_cast<float*>(pMatrix16x16_void);
|
||||
|
||||
float* pDst = pMatrix;
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
storeu_linear_all(pDst, mat[i][0]);
|
||||
storeu_linear_all(pDst + 4, mat[i][1]);
|
||||
storeu_linear_all(pDst + 8, mat[i][2]);
|
||||
storeu_linear_all(pDst + 12, mat[i][3]);
|
||||
pDst += 16;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace CPPSPMD_NAME(basisu_kernels_namespace);
|
||||
|
||||
void CPPSPMD_NAME(perceptual_distance_rgb_4_N)(int64_t* pDistance, const uint8_t* pSelectors, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err)
|
||||
{
|
||||
spmd_call< perceptual_distance_rgb_4_N >(pDistance, pSelectors, pBlock_colors, pSrc_pixels, n, early_out_err);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(linear_distance_rgb_4_N)(int64_t* pDistance, const uint8_t* pSelectors, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err)
|
||||
{
|
||||
spmd_call< linear_distance_rgb_4_N >(pDistance, pSelectors, pBlock_colors, pSrc_pixels, n, early_out_err);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(find_selectors_perceptual_rgb_4_N)(int64_t *pDistance, uint8_t* pSelectors, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err)
|
||||
{
|
||||
spmd_call< find_selectors_perceptual_rgb_4_N >(pDistance, pSelectors, pBlock_colors, pSrc_pixels, n, early_out_err);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(find_selectors_linear_rgb_4_N)(int64_t* pDistance, uint8_t* pSelectors, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_err)
|
||||
{
|
||||
spmd_call< find_selectors_linear_rgb_4_N >(pDistance, pSelectors, pBlock_colors, pSrc_pixels, n, early_out_err);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(find_lowest_error_perceptual_rgb_4_N)(int64_t* pDistance, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error)
|
||||
{
|
||||
spmd_call< find_lowest_error_perceptual_rgb_4_N >(pDistance, pBlock_colors, pSrc_pixels, n, early_out_error);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(find_lowest_error_linear_rgb_4_N)(int64_t* pDistance, const color_rgba* pBlock_colors, const color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error)
|
||||
{
|
||||
spmd_call< find_lowest_error_linear_rgb_4_N >(pDistance, pBlock_colors, pSrc_pixels, n, early_out_error);
|
||||
}
|
||||
|
||||
void CPPSPMD_NAME(update_covar_matrix_16x16)(uint32_t num_vecs, const void* pWeighted_vecs, const void* pOrigin, const uint32_t *pVec_indices, void* pMatrix16x16)
|
||||
{
|
||||
spmd_call < update_covar_matrix_16x16 >(num_vecs, pWeighted_vecs, pOrigin, pVec_indices, pMatrix16x16);
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
// basisu_kernels_sse.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_enc.h"
|
||||
|
||||
#if BASISU_SUPPORT_SSE
|
||||
|
||||
#define CPPSPMD_SSE2 0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#if __AVX__ || __AVX2__ || __AVX512F__
|
||||
#error Please check your compiler options
|
||||
#endif
|
||||
|
||||
#if CPPSPMD_SSE2
|
||||
#if __SSE4_1__ || __SSE3__ || __SSE4_2__ || __SSSE3__
|
||||
#error SSE4.1/SSE3/SSE4.2/SSSE3 cannot be enabled to use this file
|
||||
#endif
|
||||
#else
|
||||
#if !__SSE4_1__ || !__SSE3__ || !__SSSE3__
|
||||
#error Please check your compiler options
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "cppspmd_sse.h"
|
||||
|
||||
#include "cppspmd_type_aliases.h"
|
||||
|
||||
using namespace basisu;
|
||||
|
||||
#include "basisu_kernels_declares.h"
|
||||
#include "basisu_kernels_imp.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
|
||||
struct cpu_info
|
||||
{
|
||||
cpu_info() { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
bool m_has_fpu;
|
||||
bool m_has_mmx;
|
||||
bool m_has_sse;
|
||||
bool m_has_sse2;
|
||||
bool m_has_sse3;
|
||||
bool m_has_ssse3;
|
||||
bool m_has_sse41;
|
||||
bool m_has_sse42;
|
||||
bool m_has_avx;
|
||||
bool m_has_avx2;
|
||||
bool m_has_pclmulqdq;
|
||||
};
|
||||
|
||||
static void extract_x86_flags(cpu_info &info, uint32_t ecx, uint32_t edx)
|
||||
{
|
||||
info.m_has_fpu = (edx & (1 << 0)) != 0;
|
||||
info.m_has_mmx = (edx & (1 << 23)) != 0;
|
||||
info.m_has_sse = (edx & (1 << 25)) != 0;
|
||||
info.m_has_sse2 = (edx & (1 << 26)) != 0;
|
||||
info.m_has_sse3 = (ecx & (1 << 0)) != 0;
|
||||
info.m_has_ssse3 = (ecx & (1 << 9)) != 0;
|
||||
info.m_has_sse41 = (ecx & (1 << 19)) != 0;
|
||||
info.m_has_sse42 = (ecx & (1 << 20)) != 0;
|
||||
info.m_has_pclmulqdq = (ecx & (1 << 1)) != 0;
|
||||
info.m_has_avx = (ecx & (1 << 28)) != 0;
|
||||
}
|
||||
|
||||
static void extract_x86_extended_flags(cpu_info &info, uint32_t ebx)
|
||||
{
|
||||
info.m_has_avx2 = (ebx & (1 << 5)) != 0;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static void do_cpuid(uint32_t eax, uint32_t ecx, uint32_t* regs)
|
||||
{
|
||||
uint32_t ebx = 0, edx = 0;
|
||||
|
||||
#if defined(__PIC__) && defined(__i386__)
|
||||
__asm__("movl %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=D"(ebx), "+a"(eax), "+c"(ecx), "=d"(edx));
|
||||
#else
|
||||
__asm__("cpuid;" : "+b"(ebx), "+a"(eax), "+c"(ecx), "=d"(edx));
|
||||
#endif
|
||||
|
||||
regs[0] = eax; regs[1] = ebx; regs[2] = ecx; regs[3] = edx;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void get_cpuinfo(cpu_info &info)
|
||||
{
|
||||
int regs[4];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__cpuid(regs, 0);
|
||||
#else
|
||||
do_cpuid(0, 0, (uint32_t *)regs);
|
||||
#endif
|
||||
|
||||
const uint32_t max_eax = regs[0];
|
||||
|
||||
if (max_eax >= 1U)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__cpuid(regs, 1);
|
||||
#else
|
||||
do_cpuid(1, 0, (uint32_t*)regs);
|
||||
#endif
|
||||
extract_x86_flags(info, regs[2], regs[3]);
|
||||
}
|
||||
|
||||
if (max_eax >= 7U)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__cpuidex(regs, 7, 0);
|
||||
#else
|
||||
do_cpuid(7, 0, (uint32_t*)regs);
|
||||
#endif
|
||||
|
||||
extract_x86_extended_flags(info, regs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void detect_sse41()
|
||||
{
|
||||
cpu_info info;
|
||||
get_cpuinfo(info);
|
||||
|
||||
// Check for everything from SSE to SSE 4.1
|
||||
g_cpu_supports_sse41 = info.m_has_sse && info.m_has_sse2 && info.m_has_sse3 && info.m_has_ssse3 && info.m_has_sse41;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
#else // #if BASISU_SUPPORT_SSE
|
||||
namespace basisu
|
||||
{
|
||||
|
||||
void detect_sse41()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
#endif // #if BASISU_SUPPORT_SSE
|
||||
|
||||
+2538
File diff suppressed because it is too large
Load Diff
+1439
File diff suppressed because it is too large
Load Diff
+1334
File diff suppressed because it is too large
Load Diff
+143
@@ -0,0 +1,143 @@
|
||||
// basisu_opencl.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Note: Undefine or set BASISU_SUPPORT_OPENCL to 0 to completely OpenCL support.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "../transcoder/basisu.h"
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_etc.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
bool opencl_init(bool force_serialization);
|
||||
void opencl_deinit();
|
||||
bool opencl_is_available();
|
||||
|
||||
struct opencl_context;
|
||||
|
||||
// Each thread calling OpenCL should have its own opencl_context_ptr. This corresponds to a OpenCL command queue. (Confusingly, we only use a single OpenCL device "context".)
|
||||
typedef opencl_context* opencl_context_ptr;
|
||||
|
||||
opencl_context_ptr opencl_create_context();
|
||||
void opencl_destroy_context(opencl_context_ptr context);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct cl_pixel_block
|
||||
{
|
||||
color_rgba m_pixels[16]; // [y*4+x]
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// Must match BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE
|
||||
const uint32_t OPENCL_ENCODE_ETC1S_MAX_PERMS = 165;
|
||||
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks);
|
||||
|
||||
bool opencl_encode_etc1s_blocks(opencl_context_ptr pContext, etc_block* pOutput_blocks, bool perceptual, uint32_t total_perms);
|
||||
|
||||
// opencl_encode_etc1s_pixel_clusters
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct cl_pixel_cluster
|
||||
{
|
||||
uint64_t m_total_pixels;
|
||||
uint64_t m_first_pixel_index;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool opencl_encode_etc1s_pixel_clusters(
|
||||
opencl_context_ptr pContext,
|
||||
etc_block* pOutput_blocks,
|
||||
uint32_t total_clusters,
|
||||
const cl_pixel_cluster *pClusters,
|
||||
uint64_t total_pixels,
|
||||
const color_rgba *pPixels,
|
||||
const uint32_t *pPixel_weights,
|
||||
bool perceptual, uint32_t total_perms);
|
||||
|
||||
// opencl_refine_endpoint_clusterization
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct cl_block_info_struct
|
||||
{
|
||||
uint16_t m_first_cluster_ofs;
|
||||
uint16_t m_num_clusters;
|
||||
uint16_t m_cur_cluster_index;
|
||||
uint8_t m_cur_cluster_etc_inten;
|
||||
};
|
||||
|
||||
struct cl_endpoint_cluster_struct
|
||||
{
|
||||
color_rgba m_unscaled_color;
|
||||
uint8_t m_etc_inten;
|
||||
uint16_t m_cluster_index;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool opencl_refine_endpoint_clusterization(
|
||||
opencl_context_ptr pContext,
|
||||
const cl_block_info_struct *pPixel_block_info,
|
||||
uint32_t total_clusters,
|
||||
const cl_endpoint_cluster_struct *pCluster_info,
|
||||
const uint32_t *pSorted_block_indices,
|
||||
uint32_t* pOutput_cluster_indices,
|
||||
bool perceptual);
|
||||
|
||||
// opencl_find_optimal_selector_clusters_for_each_block
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct fosc_selector_struct
|
||||
{
|
||||
uint32_t m_packed_selectors; // 4x4 grid of 2-bit selectors
|
||||
};
|
||||
|
||||
struct fosc_block_struct
|
||||
{
|
||||
color_rgba m_etc_color5_inten; // unscaled 5-bit block color in RGB, alpha has block's intensity index
|
||||
uint32_t m_first_selector; // offset into selector table
|
||||
uint32_t m_num_selectors; // number of selectors to check
|
||||
};
|
||||
|
||||
struct fosc_param_struct
|
||||
{
|
||||
uint32_t m_total_blocks;
|
||||
int m_perceptual;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool opencl_find_optimal_selector_clusters_for_each_block(
|
||||
opencl_context_ptr pContext,
|
||||
const fosc_block_struct* pInput_block_info, // one per block
|
||||
uint32_t total_input_selectors,
|
||||
const fosc_selector_struct* pInput_selectors,
|
||||
const uint32_t* pSelector_cluster_indices,
|
||||
uint32_t* pOutput_selector_cluster_indices, // one per block
|
||||
bool perceptual);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ds_param_struct
|
||||
{
|
||||
uint32_t m_total_blocks;
|
||||
int m_perceptual;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool opencl_determine_selectors(
|
||||
opencl_context_ptr pContext,
|
||||
const color_rgba* pInput_etc_color5_and_inten,
|
||||
etc_block* pOutput_blocks,
|
||||
bool perceptual);
|
||||
|
||||
} // namespace basisu
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
// basisu_pvrtc1_4.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_pvrtc1_4.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
#if 0
|
||||
static const uint8_t g_pvrtc_5[32] = { 0,8,16,24,33,41,49,57,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,198,206,214,222,231,239,247,255 };
|
||||
static const uint8_t g_pvrtc_4[16] = { 0,16,33,49,66,82,99,115,140,156,173,189,206,222,239,255 };
|
||||
static const uint8_t g_pvrtc_3[8] = { 0,33,74,107,148,181,222,255 };
|
||||
static const uint8_t g_pvrtc_alpha[9] = { 0,34,68,102,136,170,204,238,255 };
|
||||
#endif
|
||||
|
||||
static const uint8_t g_pvrtc_5_nearest[256] = { 0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31 };
|
||||
static const uint8_t g_pvrtc_4_nearest[256] = { 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15 };
|
||||
#if 0
|
||||
static const uint8_t g_pvrtc_3_nearest[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
|
||||
static const uint8_t g_pvrtc_alpha_nearest[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8 };
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static const uint8_t g_pvrtc_5_floor[256] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,
|
||||
3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,
|
||||
7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
|
||||
11,11,11,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,
|
||||
15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,
|
||||
19,19,19,19,19,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,
|
||||
23,23,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,
|
||||
27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_5_ceil[256] =
|
||||
{
|
||||
0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,
|
||||
4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,
|
||||
8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12,
|
||||
12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,
|
||||
16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,
|
||||
20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,
|
||||
24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,
|
||||
28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_4_floor[256] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,
|
||||
9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,
|
||||
11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,
|
||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_4_ceil[256] =
|
||||
{
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,
|
||||
10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,
|
||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,
|
||||
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_3_floor[256] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_3_ceil[256] =
|
||||
{
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_alpha_floor[256] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8
|
||||
};
|
||||
|
||||
static const uint8_t g_pvrtc_alpha_ceil[256] =
|
||||
{
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
||||
};
|
||||
#endif
|
||||
|
||||
uint32_t pvrtc4_swizzle_uv(uint32_t width, uint32_t height, uint32_t x, uint32_t y)
|
||||
{
|
||||
assert((x < width) && (y < height) && basisu::is_pow2(height) && basisu::is_pow2(width));
|
||||
|
||||
uint32_t min_d = width, max_v = y;
|
||||
if (height < width)
|
||||
{
|
||||
min_d = height;
|
||||
max_v = x;
|
||||
}
|
||||
|
||||
// Interleave the XY LSB's
|
||||
uint32_t shift_ofs = 0, swizzled = 0;
|
||||
for (uint32_t s_bit = 1, d_bit = 1; s_bit < min_d; s_bit <<= 1, d_bit <<= 2, ++shift_ofs)
|
||||
{
|
||||
if (y & s_bit) swizzled |= d_bit;
|
||||
if (x & s_bit) swizzled |= (2 * d_bit);
|
||||
}
|
||||
|
||||
max_v >>= shift_ofs;
|
||||
|
||||
// OR in the rest of the bits from the largest dimension
|
||||
swizzled |= (max_v << (2 * shift_ofs));
|
||||
|
||||
return swizzled;
|
||||
}
|
||||
|
||||
color_rgba pvrtc4_block::get_endpoint(uint32_t endpoint_index, bool unpack) const
|
||||
{
|
||||
assert(endpoint_index < 2);
|
||||
const uint32_t packed = m_endpoints >> (endpoint_index * 16);
|
||||
|
||||
uint32_t r, g, b, a;
|
||||
if (packed & 0x8000)
|
||||
{
|
||||
// opaque 554 or 555
|
||||
if (!endpoint_index)
|
||||
{
|
||||
r = (packed >> 10) & 31;
|
||||
g = (packed >> 5) & 31;
|
||||
b = (packed >> 1) & 15;
|
||||
|
||||
if (unpack)
|
||||
{
|
||||
b = (b << 1) | (b >> 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (packed >> 10) & 31;
|
||||
g = (packed >> 5) & 31;
|
||||
b = packed & 31;
|
||||
}
|
||||
|
||||
a = unpack ? 255 : 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
// translucent 4433 or 4443
|
||||
if (!endpoint_index)
|
||||
{
|
||||
a = (packed >> 12) & 7;
|
||||
r = (packed >> 8) & 15;
|
||||
g = (packed >> 4) & 15;
|
||||
b = (packed >> 1) & 7;
|
||||
|
||||
if (unpack)
|
||||
{
|
||||
a = (a << 1);
|
||||
a = (a << 4) | a;
|
||||
|
||||
r = (r << 1) | (r >> 3);
|
||||
g = (g << 1) | (g >> 3);
|
||||
b = (b << 2) | (b >> 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a = (packed >> 12) & 7;
|
||||
r = (packed >> 8) & 15;
|
||||
g = (packed >> 4) & 15;
|
||||
b = packed & 15;
|
||||
|
||||
if (unpack)
|
||||
{
|
||||
a = (a << 1);
|
||||
a = (a << 4) | a;
|
||||
|
||||
r = (r << 1) | (r >> 3);
|
||||
g = (g << 1) | (g >> 3);
|
||||
b = (b << 1) | (b >> 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unpack)
|
||||
{
|
||||
r = (r << 3) | (r >> 2);
|
||||
g = (g << 3) | (g >> 2);
|
||||
b = (b << 3) | (b >> 2);
|
||||
}
|
||||
|
||||
assert((r < 256) && (g < 256) && (b < 256) && (a < 256));
|
||||
|
||||
return color_rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
color_rgba pvrtc4_block::get_endpoint_5554(uint32_t endpoint_index) const
|
||||
{
|
||||
assert(endpoint_index < 2);
|
||||
const uint32_t packed = m_endpoints >> (endpoint_index * 16);
|
||||
|
||||
uint32_t r, g, b, a;
|
||||
if (packed & 0x8000)
|
||||
{
|
||||
// opaque 554 or 555
|
||||
if (!endpoint_index)
|
||||
{
|
||||
r = (packed >> 10) & 31;
|
||||
g = (packed >> 5) & 31;
|
||||
b = (packed >> 1) & 15;
|
||||
|
||||
b = (b << 1) | (b >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (packed >> 10) & 31;
|
||||
g = (packed >> 5) & 31;
|
||||
b = packed & 31;
|
||||
}
|
||||
|
||||
a = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
// translucent 4433 or 4443
|
||||
if (!endpoint_index)
|
||||
{
|
||||
a = (packed >> 12) & 7;
|
||||
r = (packed >> 8) & 15;
|
||||
g = (packed >> 4) & 15;
|
||||
b = (packed >> 1) & 7;
|
||||
|
||||
a = a << 1;
|
||||
|
||||
r = (r << 1) | (r >> 3);
|
||||
g = (g << 1) | (g >> 3);
|
||||
b = (b << 2) | (b >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = (packed >> 12) & 7;
|
||||
r = (packed >> 8) & 15;
|
||||
g = (packed >> 4) & 15;
|
||||
b = packed & 15;
|
||||
|
||||
a = a << 1;
|
||||
|
||||
r = (r << 1) | (r >> 3);
|
||||
g = (g << 1) | (g >> 3);
|
||||
b = (b << 1) | (b >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
assert((r < 32) && (g < 32) && (b < 32) && (a < 16));
|
||||
|
||||
return color_rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
bool pvrtc4_image::get_interpolated_colors(uint32_t x, uint32_t y, color_rgba* pColors) const
|
||||
{
|
||||
assert((x < m_width) && (y < m_height));
|
||||
|
||||
int block_x0 = (static_cast<int>(x) - 2) >> 2;
|
||||
int block_x1 = block_x0 + 1;
|
||||
int block_y0 = (static_cast<int>(y) - 2) >> 2;
|
||||
int block_y1 = block_y0 + 1;
|
||||
|
||||
block_x0 = posmod(block_x0, m_block_width);
|
||||
block_x1 = posmod(block_x1, m_block_width);
|
||||
block_y0 = posmod(block_y0, m_block_height);
|
||||
block_y1 = posmod(block_y1, m_block_height);
|
||||
|
||||
pColors[0] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
|
||||
pColors[3] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
|
||||
|
||||
if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
|
||||
{
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
uint32_t m = (pColors[0][c] + pColors[3][c]) / 2;
|
||||
pColors[1][c] = static_cast<uint8_t>(m);
|
||||
pColors[2][c] = static_cast<uint8_t>(m);
|
||||
}
|
||||
pColors[2][3] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
pColors[1][c] = static_cast<uint8_t>((pColors[0][c] * 5 + pColors[3][c] * 3) / 8);
|
||||
pColors[2][c] = static_cast<uint8_t>((pColors[0][c] * 3 + pColors[3][c] * 5) / 8);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
color_rgba pvrtc4_image::get_pixel(uint32_t x, uint32_t y, uint32_t m) const
|
||||
{
|
||||
assert((x < m_width) && (y < m_height));
|
||||
|
||||
int block_x0 = (static_cast<int>(x) - 2) >> 2;
|
||||
int block_x1 = block_x0 + 1;
|
||||
int block_y0 = (static_cast<int>(y) - 2) >> 2;
|
||||
int block_y1 = block_y0 + 1;
|
||||
|
||||
block_x0 = posmod(block_x0, m_block_width);
|
||||
block_x1 = posmod(block_x1, m_block_width);
|
||||
block_y0 = posmod(block_y0, m_block_height);
|
||||
block_y1 = posmod(block_y1, m_block_height);
|
||||
|
||||
if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
|
||||
{
|
||||
if (m == 0)
|
||||
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
|
||||
else if (m == 3)
|
||||
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
|
||||
|
||||
color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
|
||||
color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
|
||||
|
||||
return color_rgba((l[0] + h[0]) / 2, (l[1] + h[1]) / 2, (l[2] + h[2]) / 2, (m == 2) ? 0 : (l[3] + h[3]) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m == 0)
|
||||
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
|
||||
else if (m == 3)
|
||||
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
|
||||
|
||||
color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
|
||||
color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
|
||||
|
||||
if (m == 2)
|
||||
return color_rgba((l[0] * 3 + h[0] * 5) / 8, (l[1] * 3 + h[1] * 5) / 8, (l[2] * 3 + h[2] * 5) / 8, (l[3] * 3 + h[3] * 5) / 8);
|
||||
else
|
||||
return color_rgba((l[0] * 5 + h[0] * 3) / 8, (l[1] * 5 + h[1] * 3) / 8, (l[2] * 5 + h[2] * 3) / 8, (l[3] * 5 + h[3] * 3) / 8);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t pvrtc4_image::local_endpoint_optimization_opaque(uint32_t bx, uint32_t by, const image& orig_img, bool perceptual)
|
||||
{
|
||||
uint64_t initial_error = evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false);
|
||||
if (!initial_error)
|
||||
return initial_error;
|
||||
|
||||
vec3F c_avg_orig(0);
|
||||
|
||||
for (int y = 0; y < 7; y++)
|
||||
{
|
||||
const uint32_t py = wrap_y(by * 4 + y - 1);
|
||||
for (uint32_t x = 0; x < 7; x++)
|
||||
{
|
||||
const uint32_t px = wrap_x(bx * 4 + x - 1);
|
||||
|
||||
const color_rgba& c = orig_img(px, py);
|
||||
|
||||
c_avg_orig[0] += c[0];
|
||||
c_avg_orig[1] += c[1];
|
||||
c_avg_orig[2] += c[2];
|
||||
}
|
||||
}
|
||||
|
||||
c_avg_orig *= 1.0f / 49.0f;
|
||||
|
||||
vec3F quant_colors[2];
|
||||
quant_colors[0].set(c_avg_orig);
|
||||
quant_colors[0] -= vec3F(.0125f);
|
||||
|
||||
quant_colors[1].set(c_avg_orig);
|
||||
quant_colors[1] += vec3F(.0125f);
|
||||
|
||||
float total_weight[2];
|
||||
|
||||
bool success = true;
|
||||
|
||||
for (uint32_t pass = 0; pass < 4; pass++)
|
||||
{
|
||||
vec3F new_colors[2] = { vec3F(0), vec3F(0) };
|
||||
memset(total_weight, 0, sizeof(total_weight));
|
||||
|
||||
static const float s_weights[7][7] =
|
||||
{
|
||||
{ 1.000000f, 1.637089f, 2.080362f, 2.242640f, 2.080362f, 1.637089f, 1.000000f },
|
||||
{ 1.637089f, 2.414213f, 3.006572f, 3.242640f, 3.006572f, 2.414213f, 1.637089f },
|
||||
{ 2.080362f, 3.006572f, 3.828426f, 4.242640f, 3.828426f, 3.006572f, 2.080362f },
|
||||
{ 2.242640f, 3.242640f, 4.242640f, 5.000000f, 4.242640f, 3.242640f, 2.242640f },
|
||||
{ 2.080362f, 3.006572f, 3.828426f, 4.242640f, 3.828426f, 3.006572f, 2.080362f },
|
||||
{ 1.637089f, 2.414213f, 3.006572f, 3.242640f, 3.006572f, 2.414213f, 1.637089f },
|
||||
{ 1.000000f, 1.637089f, 2.080362f, 2.242640f, 2.080362f, 1.637089f, 1.000000f }
|
||||
};
|
||||
|
||||
for (int y = 0; y < 7; y++)
|
||||
{
|
||||
const uint32_t py = wrap_y(by * 4 + y - 1);
|
||||
for (uint32_t x = 0; x < 7; x++)
|
||||
{
|
||||
const uint32_t px = wrap_x(bx * 4 + x - 1);
|
||||
|
||||
const color_rgba& orig_c = orig_img(px, py);
|
||||
|
||||
vec3F color(orig_c[0], orig_c[1], orig_c[2]);
|
||||
|
||||
uint32_t c = quant_colors[0].squared_distance(color) > quant_colors[1].squared_distance(color);
|
||||
|
||||
const float weight = s_weights[y][x];
|
||||
new_colors[c] += color * weight;
|
||||
|
||||
total_weight[c] += weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (!total_weight[0] || !total_weight[1])
|
||||
success = false;
|
||||
|
||||
quant_colors[0] = new_colors[0] / (float)total_weight[0];
|
||||
quant_colors[1] = new_colors[1] / (float)total_weight[1];
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
quant_colors[0] = c_avg_orig;
|
||||
quant_colors[1] = c_avg_orig;
|
||||
}
|
||||
|
||||
vec4F colors[2] = { quant_colors[0], quant_colors[1] };
|
||||
|
||||
colors[0] += vec3F(.5f);
|
||||
colors[1] += vec3F(.5f);
|
||||
color_rgba color_0((int)colors[0][0], (int)colors[0][1], (int)colors[0][2], 0);
|
||||
color_rgba color_1((int)colors[1][0], (int)colors[1][1], (int)colors[1][2], 0);
|
||||
|
||||
pvrtc4_block cur_blocks[3][3];
|
||||
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
const uint32_t block_x = wrap_block_x(bx + x);
|
||||
const uint32_t block_y = wrap_block_y(by + y);
|
||||
cur_blocks[x + 1][y + 1] = m_blocks(block_x, block_y);
|
||||
}
|
||||
}
|
||||
|
||||
color_rgba l1(0), h1(0);
|
||||
|
||||
l1[0] = g_pvrtc_5_nearest[color_0[0]];
|
||||
h1[0] = g_pvrtc_5_nearest[color_1[0]];
|
||||
|
||||
l1[1] = g_pvrtc_5_nearest[color_0[1]];
|
||||
h1[1] = g_pvrtc_5_nearest[color_1[1]];
|
||||
|
||||
l1[2] = g_pvrtc_4_nearest[color_0[2]];
|
||||
h1[2] = g_pvrtc_5_nearest[color_0[2]];
|
||||
|
||||
l1[3] = 0;
|
||||
h1[3] = 0;
|
||||
|
||||
m_blocks(bx, by).set_endpoint_raw(0, l1, true);
|
||||
m_blocks(bx, by).set_endpoint_raw(1, h1, true);
|
||||
|
||||
uint64_t e03_err_0 = remap_pixels_influenced_by_endpoint(bx, by, orig_img, perceptual, false);
|
||||
|
||||
pvrtc4_block blocks0[3][3];
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
const uint32_t block_x = wrap_block_x(bx + x);
|
||||
const uint32_t block_y = wrap_block_y(by + y);
|
||||
blocks0[x + 1][y + 1] = m_blocks(block_x, block_y);
|
||||
}
|
||||
}
|
||||
|
||||
l1[0] = g_pvrtc_5_nearest[color_1[0]];
|
||||
h1[0] = g_pvrtc_5_nearest[color_0[0]];
|
||||
|
||||
l1[1] = g_pvrtc_5_nearest[color_1[1]];
|
||||
h1[1] = g_pvrtc_5_nearest[color_0[1]];
|
||||
|
||||
l1[2] = g_pvrtc_4_nearest[color_1[2]];
|
||||
h1[2] = g_pvrtc_5_nearest[color_0[2]];
|
||||
|
||||
l1[3] = 0;
|
||||
h1[3] = 0;
|
||||
|
||||
m_blocks(bx, by).set_endpoint_raw(0, l1, true);
|
||||
m_blocks(bx, by).set_endpoint_raw(1, h1, true);
|
||||
|
||||
uint64_t e03_err_1 = remap_pixels_influenced_by_endpoint(bx, by, orig_img, perceptual, false);
|
||||
|
||||
if (initial_error < basisu::minimum(e03_err_0, e03_err_1))
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
const uint32_t block_x = wrap_block_x(bx + x);
|
||||
const uint32_t block_y = wrap_block_y(by + y);
|
||||
m_blocks(block_x, block_y) = cur_blocks[x + 1][y + 1];
|
||||
}
|
||||
}
|
||||
return initial_error;
|
||||
}
|
||||
else if (e03_err_0 < e03_err_1)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
const uint32_t block_x = wrap_block_x(bx + x);
|
||||
const uint32_t block_y = wrap_block_y(by + y);
|
||||
m_blocks(block_x, block_y) = blocks0[x + 1][y + 1];
|
||||
}
|
||||
}
|
||||
assert(e03_err_0 == evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false));
|
||||
return e03_err_0;
|
||||
}
|
||||
|
||||
assert(e03_err_1 == evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false));
|
||||
return e03_err_1;
|
||||
}
|
||||
|
||||
} // basisu
|
||||
+457
@@ -0,0 +1,457 @@
|
||||
// basisu_pvrtc1_4.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "basisu_gpu_texture.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
enum
|
||||
{
|
||||
PVRTC2_MIN_WIDTH = 16,
|
||||
PVRTC2_MIN_HEIGHT = 8,
|
||||
PVRTC4_MIN_WIDTH = 8,
|
||||
PVRTC4_MIN_HEIGHT = 8
|
||||
};
|
||||
|
||||
struct pvrtc4_block
|
||||
{
|
||||
uint32_t m_modulation;
|
||||
uint32_t m_endpoints;
|
||||
|
||||
pvrtc4_block() : m_modulation(0), m_endpoints(0) { }
|
||||
|
||||
inline bool operator== (const pvrtc4_block& rhs) const
|
||||
{
|
||||
return (m_modulation == rhs.m_modulation) && (m_endpoints == rhs.m_endpoints);
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_modulation = 0;
|
||||
m_endpoints = 0;
|
||||
}
|
||||
|
||||
inline bool get_block_uses_transparent_modulation() const
|
||||
{
|
||||
return (m_endpoints & 1) != 0;
|
||||
}
|
||||
|
||||
inline bool is_endpoint_opaque(uint32_t endpoint_index) const
|
||||
{
|
||||
static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U };
|
||||
return (m_endpoints & s_bitmasks[open_range_check(endpoint_index, 2U)]) != 0;
|
||||
}
|
||||
|
||||
// Returns raw endpoint or 8888
|
||||
color_rgba get_endpoint(uint32_t endpoint_index, bool unpack) const;
|
||||
|
||||
color_rgba get_endpoint_5554(uint32_t endpoint_index) const;
|
||||
|
||||
static uint32_t get_component_precision_in_bits(uint32_t c, uint32_t endpoint_index, bool opaque_endpoint)
|
||||
{
|
||||
static const uint32_t s_comp_prec[4][4] =
|
||||
{
|
||||
// R0 G0 B0 A0 R1 G1 B1 A1
|
||||
{ 4, 4, 3, 3 }, { 4, 4, 4, 3 }, // transparent endpoint
|
||||
|
||||
{ 5, 5, 4, 0 }, { 5, 5, 5, 0 } // opaque endpoint
|
||||
};
|
||||
return s_comp_prec[open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)][open_range_check(c, 4U)];
|
||||
}
|
||||
|
||||
static color_rgba get_color_precision_in_bits(uint32_t endpoint_index, bool opaque_endpoint)
|
||||
{
|
||||
static const color_rgba s_color_prec[4] =
|
||||
{
|
||||
color_rgba(4, 4, 3, 3), color_rgba(4, 4, 4, 3), // transparent endpoint
|
||||
color_rgba(5, 5, 4, 0), color_rgba(5, 5, 5, 0) // opaque endpoint
|
||||
};
|
||||
return s_color_prec[open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)];
|
||||
}
|
||||
|
||||
inline uint32_t get_modulation(uint32_t x, uint32_t y) const
|
||||
{
|
||||
assert((x < 4) && (y < 4));
|
||||
return (m_modulation >> ((y * 4 + x) * 2)) & 3;
|
||||
}
|
||||
|
||||
inline void set_modulation(uint32_t x, uint32_t y, uint32_t s)
|
||||
{
|
||||
assert((x < 4) && (y < 4) && (s < 4));
|
||||
uint32_t n = (y * 4 + x) * 2;
|
||||
m_modulation = (m_modulation & (~(3 << n))) | (s << n);
|
||||
assert(get_modulation(x, y) == s);
|
||||
}
|
||||
|
||||
// Scaled by 8
|
||||
inline const uint32_t* get_scaled_modulation_values(bool block_uses_transparent_modulation) const
|
||||
{
|
||||
static const uint32_t s_block_scales[2][4] = { { 0, 3, 5, 8 }, { 0, 4, 4, 8 } };
|
||||
return s_block_scales[block_uses_transparent_modulation];
|
||||
}
|
||||
|
||||
// Scaled by 8
|
||||
inline uint32_t get_scaled_modulation(uint32_t x, uint32_t y) const
|
||||
{
|
||||
return get_scaled_modulation_values(get_block_uses_transparent_modulation())[get_modulation(x, y)];
|
||||
}
|
||||
|
||||
inline void byte_swap()
|
||||
{
|
||||
m_modulation = byteswap32(m_modulation);
|
||||
m_endpoints = byteswap32(m_endpoints);
|
||||
}
|
||||
|
||||
// opaque endpoints: 554, 555
|
||||
// transparent endpoints: 3443, 3444
|
||||
inline void set_endpoint_raw(uint32_t endpoint_index, const color_rgba& c, bool opaque_endpoint)
|
||||
{
|
||||
assert(endpoint_index < 2);
|
||||
const uint32_t m = m_endpoints & 1;
|
||||
uint32_t r = c[0], g = c[1], b = c[2], a = c[3];
|
||||
|
||||
uint32_t packed;
|
||||
|
||||
if (opaque_endpoint)
|
||||
{
|
||||
if (!endpoint_index)
|
||||
{
|
||||
// 554
|
||||
// 1RRRRRGGGGGBBBBM
|
||||
assert((r < 32) && (g < 32) && (b < 16));
|
||||
packed = 0x8000 | (r << 10) | (g << 5) | (b << 1) | m;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 555
|
||||
// 1RRRRRGGGGGBBBBB
|
||||
assert((r < 32) && (g < 32) && (b < 32));
|
||||
packed = 0x8000 | (r << 10) | (g << 5) | b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!endpoint_index)
|
||||
{
|
||||
// 3443
|
||||
// 0AAA RRRR GGGG BBBM
|
||||
assert((r < 16) && (g < 16) && (b < 8) && (a < 8));
|
||||
packed = (a << 12) | (r << 8) | (g << 4) | (b << 1) | m;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 3444
|
||||
// 0AAA RRRR GGGG BBBB
|
||||
assert((r < 16) && (g < 16) && (b < 16) && (a < 8));
|
||||
packed = (a << 12) | (r << 8) | (g << 4) | b;
|
||||
}
|
||||
}
|
||||
|
||||
assert(packed <= 0xFFFF);
|
||||
|
||||
if (endpoint_index)
|
||||
m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16);
|
||||
else
|
||||
m_endpoints = (m_endpoints & 0xFFFF0000U) | packed;
|
||||
}
|
||||
};
|
||||
|
||||
typedef vector2D<pvrtc4_block> pvrtc4_block_vector2D;
|
||||
|
||||
uint32_t pvrtc4_swizzle_uv(uint32_t XSize, uint32_t YSize, uint32_t XPos, uint32_t YPos);
|
||||
|
||||
class pvrtc4_image
|
||||
{
|
||||
public:
|
||||
inline pvrtc4_image() :
|
||||
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline pvrtc4_image(uint32_t width, uint32_t height) :
|
||||
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
|
||||
{
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_block_width = 0;
|
||||
m_block_height = 0;
|
||||
m_blocks.clear();
|
||||
m_uses_alpha = false;
|
||||
}
|
||||
|
||||
inline void resize(uint32_t width, uint32_t height)
|
||||
{
|
||||
if ((width == m_width) && (height == m_height))
|
||||
return;
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
m_block_width = (width + 3) >> 2;
|
||||
m_block_height = (height + 3) >> 2;
|
||||
|
||||
m_blocks.resize(m_block_width, m_block_height);
|
||||
}
|
||||
|
||||
inline uint32_t get_width() const { return m_width; }
|
||||
inline uint32_t get_height() const { return m_height; }
|
||||
|
||||
inline uint32_t get_block_width() const { return m_block_width; }
|
||||
inline uint32_t get_block_height() const { return m_block_height; }
|
||||
|
||||
inline const pvrtc4_block_vector2D &get_blocks() const { return m_blocks; }
|
||||
inline pvrtc4_block_vector2D &get_blocks() { return m_blocks; }
|
||||
|
||||
inline uint32_t get_total_blocks() const { return m_block_width * m_block_height; }
|
||||
|
||||
inline bool get_uses_alpha() const { return m_uses_alpha; }
|
||||
inline void set_uses_alpha(bool uses_alpha) { m_uses_alpha = uses_alpha; }
|
||||
|
||||
inline bool are_blocks_equal(const pvrtc4_image& rhs) const
|
||||
{
|
||||
return m_blocks == rhs.m_blocks;
|
||||
}
|
||||
|
||||
inline void set_to_black()
|
||||
{
|
||||
memset(m_blocks.get_ptr(), 0, m_blocks.size_in_bytes());
|
||||
}
|
||||
|
||||
inline bool get_block_uses_transparent_modulation(uint32_t bx, uint32_t by) const
|
||||
{
|
||||
return m_blocks(bx, by).get_block_uses_transparent_modulation();
|
||||
}
|
||||
|
||||
inline bool is_endpoint_opaque(uint32_t bx, uint32_t by, uint32_t endpoint_index) const
|
||||
{
|
||||
return m_blocks(bx, by).is_endpoint_opaque(endpoint_index);
|
||||
}
|
||||
|
||||
color_rgba get_endpoint(uint32_t bx, uint32_t by, uint32_t endpoint_index, bool unpack) const
|
||||
{
|
||||
assert((bx < m_block_width) && (by < m_block_height));
|
||||
return m_blocks(bx, by).get_endpoint(endpoint_index, unpack);
|
||||
}
|
||||
|
||||
inline uint32_t get_modulation(uint32_t x, uint32_t y) const
|
||||
{
|
||||
assert((x < m_width) && (y < m_height));
|
||||
return m_blocks(x >> 2, y >> 2).get_modulation(x & 3, y & 3);
|
||||
}
|
||||
|
||||
// Returns true if the block uses transparent modulation.
|
||||
bool get_interpolated_colors(uint32_t x, uint32_t y, color_rgba* pColors) const;
|
||||
|
||||
color_rgba get_pixel(uint32_t x, uint32_t y, uint32_t m) const;
|
||||
|
||||
inline color_rgba get_pixel(uint32_t x, uint32_t y) const
|
||||
{
|
||||
assert((x < m_width) && (y < m_height));
|
||||
return get_pixel(x, y, m_blocks(x >> 2, y >> 2).get_modulation(x & 3, y & 3));
|
||||
}
|
||||
|
||||
void deswizzle()
|
||||
{
|
||||
pvrtc4_block_vector2D temp(m_blocks);
|
||||
|
||||
for (uint32_t y = 0; y < m_block_height; y++)
|
||||
for (uint32_t x = 0; x < m_block_width; x++)
|
||||
m_blocks(x, y) = temp[pvrtc4_swizzle_uv(m_block_width, m_block_height, x, y)];
|
||||
}
|
||||
|
||||
void swizzle()
|
||||
{
|
||||
pvrtc4_block_vector2D temp(m_blocks);
|
||||
|
||||
for (uint32_t y = 0; y < m_block_height; y++)
|
||||
for (uint32_t x = 0; x < m_block_width; x++)
|
||||
m_blocks[pvrtc4_swizzle_uv(m_block_width, m_block_height, x, y)] = temp(x, y);
|
||||
}
|
||||
|
||||
void unpack_all_pixels(image& img) const
|
||||
{
|
||||
img.crop(m_width, m_height);
|
||||
|
||||
for (uint32_t y = 0; y < m_height; y++)
|
||||
for (uint32_t x = 0; x < m_width; x++)
|
||||
img(x, y) = get_pixel(x, y);
|
||||
}
|
||||
|
||||
void unpack_block(image &dst, uint32_t block_x, uint32_t block_y)
|
||||
{
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
dst(x, y) = get_pixel(block_x * 4 + x, block_y * 4 + y);
|
||||
}
|
||||
|
||||
inline int wrap_x(int x) const
|
||||
{
|
||||
return posmod(x, m_width);
|
||||
}
|
||||
|
||||
inline int wrap_y(int y) const
|
||||
{
|
||||
return posmod(y, m_height);
|
||||
}
|
||||
|
||||
inline int wrap_block_x(int bx) const
|
||||
{
|
||||
return posmod(bx, m_block_width);
|
||||
}
|
||||
|
||||
inline int wrap_block_y(int by) const
|
||||
{
|
||||
return posmod(by, m_block_height);
|
||||
}
|
||||
|
||||
inline vec2F get_interpolation_factors(uint32_t x, uint32_t y) const
|
||||
{
|
||||
// 0 1 2 3
|
||||
// 2 3 0 1
|
||||
// .5 .75 0 .25
|
||||
static const float s_interp[4] = { 2, 3, 0, 1 };
|
||||
return vec2F(s_interp[x & 3], s_interp[y & 3]);
|
||||
}
|
||||
|
||||
inline color_rgba interpolate(int x, int y,
|
||||
const color_rgba& p, const color_rgba& q,
|
||||
const color_rgba& r, const color_rgba& s) const
|
||||
{
|
||||
static const int s_interp[4] = { 2, 3, 0, 1 };
|
||||
const int u_interp = s_interp[x & 3];
|
||||
const int v_interp = s_interp[y & 3];
|
||||
|
||||
color_rgba result;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
int t = p[c] * 4 + u_interp * ((int)q[c] - (int)p[c]);
|
||||
int b = r[c] * 4 + u_interp * ((int)s[c] - (int)r[c]);
|
||||
int v = t * 4 + v_interp * (b - t);
|
||||
if (c < 3)
|
||||
{
|
||||
v >>= 1;
|
||||
v += (v >> 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
v += (v >> 4);
|
||||
}
|
||||
assert((v >= 0) && (v < 256));
|
||||
result[c] = static_cast<uint8_t>(v);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void set_modulation(uint32_t x, uint32_t y, uint32_t s)
|
||||
{
|
||||
assert((x < m_width) && (y < m_height));
|
||||
return m_blocks(x >> 2, y >> 2).set_modulation(x & 3, y & 3, s);
|
||||
}
|
||||
|
||||
inline uint64_t map_pixel(uint32_t x, uint32_t y, const color_rgba& c, bool perceptual, bool alpha_is_significant, bool record = true)
|
||||
{
|
||||
color_rgba v[4];
|
||||
get_interpolated_colors(x, y, v);
|
||||
|
||||
uint64_t best_dist = color_distance(perceptual, c, v[0], alpha_is_significant);
|
||||
uint32_t best_v = 0;
|
||||
for (uint32_t i = 1; i < 4; i++)
|
||||
{
|
||||
uint64_t dist = color_distance(perceptual, c, v[i], alpha_is_significant);
|
||||
if (dist < best_dist)
|
||||
{
|
||||
best_dist = dist;
|
||||
best_v = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (record)
|
||||
set_modulation(x, y, best_v);
|
||||
|
||||
return best_dist;
|
||||
}
|
||||
|
||||
inline uint64_t remap_pixels_influenced_by_endpoint(uint32_t bx, uint32_t by, const image& orig_img, bool perceptual, bool alpha_is_significant)
|
||||
{
|
||||
uint64_t total_error = 0;
|
||||
|
||||
for (int yd = -3; yd <= 3; yd++)
|
||||
{
|
||||
const int y = wrap_y((int)by * 4 + 2 + yd);
|
||||
|
||||
for (int xd = -3; xd <= 3; xd++)
|
||||
{
|
||||
const int x = wrap_x((int)bx * 4 + 2 + xd);
|
||||
|
||||
total_error += map_pixel(x, y, orig_img(x, y), perceptual, alpha_is_significant);
|
||||
}
|
||||
}
|
||||
|
||||
return total_error;
|
||||
}
|
||||
|
||||
inline uint64_t evaluate_1x1_endpoint_error(uint32_t bx, uint32_t by, const image& orig_img, bool perceptual, bool alpha_is_significant, uint64_t threshold_error = 0) const
|
||||
{
|
||||
uint64_t total_error = 0;
|
||||
|
||||
for (int yd = -3; yd <= 3; yd++)
|
||||
{
|
||||
const int y = wrap_y((int)by * 4 + 2 + yd);
|
||||
|
||||
for (int xd = -3; xd <= 3; xd++)
|
||||
{
|
||||
const int x = wrap_x((int)bx * 4 + 2 + xd);
|
||||
|
||||
total_error += color_distance(perceptual, get_pixel(x, y), orig_img(x, y), alpha_is_significant);
|
||||
|
||||
if ((threshold_error) && (total_error >= threshold_error))
|
||||
return total_error;
|
||||
}
|
||||
}
|
||||
|
||||
return total_error;
|
||||
}
|
||||
|
||||
uint64_t local_endpoint_optimization_opaque(uint32_t bx, uint32_t by, const image& orig_img, bool perceptual);
|
||||
|
||||
inline uint64_t map_all_pixels(const image& img, bool perceptual, bool alpha_is_significant)
|
||||
{
|
||||
assert(m_width == img.get_width());
|
||||
assert(m_height == img.get_height());
|
||||
|
||||
uint64_t total_error = 0;
|
||||
for (uint32_t y = 0; y < img.get_height(); y++)
|
||||
for (uint32_t x = 0; x < img.get_width(); x++)
|
||||
total_error += map_pixel(x, y, img(x, y), perceptual, alpha_is_significant);
|
||||
|
||||
return total_error;
|
||||
}
|
||||
|
||||
public:
|
||||
uint32_t m_width, m_height;
|
||||
pvrtc4_block_vector2D m_blocks;
|
||||
uint32_t m_block_width, m_block_height;
|
||||
|
||||
bool m_uses_alpha;
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
@@ -0,0 +1,340 @@
|
||||
// basisu_resampler_filters.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_resampler_filters.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
#define BOX_FILTER_SUPPORT (0.5f)
|
||||
static float box_filter(float t) /* pulse/Fourier window */
|
||||
{
|
||||
// make_clist() calls the filter function with t inverted (pos = left, neg = right)
|
||||
if ((t >= -0.5f) && (t < 0.5f))
|
||||
return 1.0f;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#define TENT_FILTER_SUPPORT (1.0f)
|
||||
static float tent_filter(float t) /* box (*) box, bilinear/triangle */
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 1.0f)
|
||||
return 1.0f - t;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#define BELL_SUPPORT (1.5f)
|
||||
static float bell_filter(float t) /* box (*) box (*) box */
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < .5f)
|
||||
return (.75f - (t * t));
|
||||
|
||||
if (t < 1.5f)
|
||||
{
|
||||
t = (t - 1.5f);
|
||||
return (.5f * (t * t));
|
||||
}
|
||||
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define B_SPLINE_SUPPORT (2.0f)
|
||||
static float B_spline_filter(float t) /* box (*) box (*) box (*) box */
|
||||
{
|
||||
float tt;
|
||||
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 1.0f)
|
||||
{
|
||||
tt = t * t;
|
||||
return ((.5f * tt * t) - tt + (2.0f / 3.0f));
|
||||
}
|
||||
else if (t < 2.0f)
|
||||
{
|
||||
t = 2.0f - t;
|
||||
return ((1.0f / 6.0f) * (t * t * t));
|
||||
}
|
||||
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
// Dodgson, N., "Quadratic Interpolation for Image Resampling"
|
||||
#define QUADRATIC_SUPPORT 1.5f
|
||||
static float quadratic(float t, const float R)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
if (t < QUADRATIC_SUPPORT)
|
||||
{
|
||||
float tt = t * t;
|
||||
if (t <= .5f)
|
||||
return (-2.0f * R) * tt + .5f * (R + 1.0f);
|
||||
else
|
||||
return (R * tt) + (-2.0f * R - .5f) * t + (3.0f / 4.0f) * (R + 1.0f);
|
||||
}
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static float quadratic_interp_filter(float t)
|
||||
{
|
||||
return quadratic(t, 1.0f);
|
||||
}
|
||||
|
||||
static float quadratic_approx_filter(float t)
|
||||
{
|
||||
return quadratic(t, .5f);
|
||||
}
|
||||
|
||||
static float quadratic_mix_filter(float t)
|
||||
{
|
||||
return quadratic(t, .8f);
|
||||
}
|
||||
|
||||
// Mitchell, D. and A. Netravali, "Reconstruction Filters in Computer Graphics."
|
||||
// Computer Graphics, Vol. 22, No. 4, pp. 221-228.
|
||||
// (B, C)
|
||||
// (1/3, 1/3) - Defaults recommended by Mitchell and Netravali
|
||||
// (1, 0) - Equivalent to the Cubic B-Spline
|
||||
// (0, 0.5) - Equivalent to the Catmull-Rom Spline
|
||||
// (0, C) - The family of Cardinal Cubic Splines
|
||||
// (B, 0) - Duff's tensioned B-Splines.
|
||||
static float mitchell(float t, const float B, const float C)
|
||||
{
|
||||
float tt;
|
||||
|
||||
tt = t * t;
|
||||
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 1.0f)
|
||||
{
|
||||
t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt)) + ((-18.0f + 12.0f * B + 6.0f * C) * tt) + (6.0f - 2.0f * B));
|
||||
|
||||
return (t / 6.0f);
|
||||
}
|
||||
else if (t < 2.0f)
|
||||
{
|
||||
t = (((-1.0f * B - 6.0f * C) * (t * tt)) + ((6.0f * B + 30.0f * C) * tt) + ((-12.0f * B - 48.0f * C) * t) + (8.0f * B + 24.0f * C));
|
||||
|
||||
return (t / 6.0f);
|
||||
}
|
||||
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define MITCHELL_SUPPORT (2.0f)
|
||||
static float mitchell_filter(float t)
|
||||
{
|
||||
return mitchell(t, 1.0f / 3.0f, 1.0f / 3.0f);
|
||||
}
|
||||
|
||||
#define CATMULL_ROM_SUPPORT (2.0f)
|
||||
static float catmull_rom_filter(float t)
|
||||
{
|
||||
return mitchell(t, 0.0f, .5f);
|
||||
}
|
||||
|
||||
static double sinc(double x)
|
||||
{
|
||||
x = (x * M_PI);
|
||||
|
||||
if ((x < 0.01f) && (x > -0.01f))
|
||||
return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f);
|
||||
|
||||
return sin(x) / x;
|
||||
}
|
||||
|
||||
static float clean(double t)
|
||||
{
|
||||
const float EPSILON = .0000125f;
|
||||
if (fabs(t) < EPSILON)
|
||||
return 0.0f;
|
||||
return (float)t;
|
||||
}
|
||||
|
||||
//static double blackman_window(double x)
|
||||
//{
|
||||
// return .42f + .50f * cos(M_PI*x) + .08f * cos(2.0f*M_PI*x);
|
||||
//}
|
||||
|
||||
static double blackman_exact_window(double x)
|
||||
{
|
||||
return 0.42659071f + 0.49656062f * cos(M_PI * x) + 0.07684867f * cos(2.0f * M_PI * x);
|
||||
}
|
||||
|
||||
#define BLACKMAN_SUPPORT (3.0f)
|
||||
static float blackman_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 3.0f)
|
||||
//return clean(sinc(t) * blackman_window(t / 3.0f));
|
||||
return clean(sinc(t) * blackman_exact_window(t / 3.0f));
|
||||
else
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define GAUSSIAN_SUPPORT (1.25f)
|
||||
static float gaussian_filter(float t) // with blackman window
|
||||
{
|
||||
if (t < 0)
|
||||
t = -t;
|
||||
if (t < GAUSSIAN_SUPPORT)
|
||||
return clean(exp(-2.0f * t * t) * sqrt(2.0f / M_PI) * blackman_exact_window(t / GAUSSIAN_SUPPORT));
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Windowed sinc -- see "Jimm Blinn's Corner: Dirty Pixels" pg. 26.
|
||||
#define LANCZOS3_SUPPORT (3.0f)
|
||||
static float lanczos3_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 3.0f)
|
||||
return clean(sinc(t) * sinc(t / 3.0f));
|
||||
else
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define LANCZOS4_SUPPORT (4.0f)
|
||||
static float lanczos4_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 4.0f)
|
||||
return clean(sinc(t) * sinc(t / 4.0f));
|
||||
else
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define LANCZOS6_SUPPORT (6.0f)
|
||||
static float lanczos6_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 6.0f)
|
||||
return clean(sinc(t) * sinc(t / 6.0f));
|
||||
else
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define LANCZOS12_SUPPORT (12.0f)
|
||||
static float lanczos12_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < 12.0f)
|
||||
return clean(sinc(t) * sinc(t / 12.0f));
|
||||
else
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
static double bessel0(double x)
|
||||
{
|
||||
const double EPSILON_RATIO = 1E-16;
|
||||
double xh, sum, pow, ds;
|
||||
int k;
|
||||
|
||||
xh = 0.5 * x;
|
||||
sum = 1.0;
|
||||
pow = 1.0;
|
||||
k = 0;
|
||||
ds = 1.0;
|
||||
while (ds > sum * EPSILON_RATIO) // FIXME: Shouldn't this stop after X iterations for max. safety?
|
||||
{
|
||||
++k;
|
||||
pow = pow * (xh / k);
|
||||
ds = pow * pow;
|
||||
sum = sum + ds;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
//static const float KAISER_ALPHA = 4.0;
|
||||
static double kaiser(double alpha, double half_width, double x)
|
||||
{
|
||||
const double ratio = (x / half_width);
|
||||
return bessel0(alpha * sqrt(1 - ratio * ratio)) / bessel0(alpha);
|
||||
}
|
||||
|
||||
#define KAISER_SUPPORT 3
|
||||
static float kaiser_filter(float t)
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
|
||||
if (t < KAISER_SUPPORT)
|
||||
{
|
||||
// db atten
|
||||
const float att = 40.0f;
|
||||
const float alpha = (float)(exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 * (att - 20.96));
|
||||
//const float alpha = KAISER_ALPHA;
|
||||
return (float)clean(sinc(t) * kaiser(alpha, KAISER_SUPPORT, t));
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
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 },
|
||||
{ "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);
|
||||
|
||||
int find_resample_filter(const char *pName)
|
||||
{
|
||||
for (int i = 0; i < g_num_resample_filters; i++)
|
||||
if (strcmp(pName, g_resample_filters[i].name) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
} // namespace basisu
|
||||
+844
@@ -0,0 +1,844 @@
|
||||
// basisu_resampler.cpp
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_resampler.h"
|
||||
#include "basisu_resampler_filters.h"
|
||||
|
||||
#define RESAMPLER_DEBUG 0
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
static inline int resampler_range_check(int v, int h)
|
||||
{
|
||||
BASISU_NOTE_UNUSED(h);
|
||||
assert((v >= 0) && (v < h));
|
||||
return v;
|
||||
}
|
||||
|
||||
// Float to int cast with truncation.
|
||||
static inline int cast_to_int(Resample_Real i)
|
||||
{
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
// Ensure that the contributing source sample is within bounds. If not, reflect, clamp, or wrap.
|
||||
int Resampler::reflect(const int j, const int src_x, const Boundary_Op boundary_op)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (j < 0)
|
||||
{
|
||||
if (boundary_op == BOUNDARY_REFLECT)
|
||||
{
|
||||
n = -j;
|
||||
|
||||
if (n >= src_x)
|
||||
n = src_x - 1;
|
||||
}
|
||||
else if (boundary_op == BOUNDARY_WRAP)
|
||||
n = posmod(j, src_x);
|
||||
else
|
||||
n = 0;
|
||||
}
|
||||
else if (j >= src_x)
|
||||
{
|
||||
if (boundary_op == BOUNDARY_REFLECT)
|
||||
{
|
||||
n = (src_x - j) + (src_x - 1);
|
||||
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
}
|
||||
else if (boundary_op == BOUNDARY_WRAP)
|
||||
n = posmod(j, src_x);
|
||||
else
|
||||
n = src_x - 1;
|
||||
}
|
||||
else
|
||||
n = j;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// The make_clist() method generates, for all destination samples,
|
||||
// the list of all source samples with non-zero weighted contributions.
|
||||
Resampler::Contrib_List * Resampler::make_clist(
|
||||
int src_x, int dst_x, Boundary_Op boundary_op,
|
||||
Resample_Real(*Pfilter)(Resample_Real),
|
||||
Resample_Real filter_support,
|
||||
Resample_Real filter_scale,
|
||||
Resample_Real src_ofs)
|
||||
{
|
||||
struct Contrib_Bounds
|
||||
{
|
||||
// The center of the range in DISCRETE coordinates (pixel center = 0.0f).
|
||||
Resample_Real center;
|
||||
int left, right;
|
||||
};
|
||||
|
||||
int i, j, k, n, left, right;
|
||||
Resample_Real total_weight;
|
||||
Resample_Real xscale, center, half_width, weight;
|
||||
Contrib_List* Pcontrib;
|
||||
Contrib* Pcpool;
|
||||
Contrib* Pcpool_next;
|
||||
Contrib_Bounds* Pcontrib_bounds;
|
||||
|
||||
if ((Pcontrib = (Contrib_List*)calloc(dst_x, sizeof(Contrib_List))) == NULL)
|
||||
return NULL;
|
||||
|
||||
Pcontrib_bounds = (Contrib_Bounds*)calloc(dst_x, sizeof(Contrib_Bounds));
|
||||
if (!Pcontrib_bounds)
|
||||
{
|
||||
free(Pcontrib);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
const Resample_Real oo_filter_scale = 1.0f / filter_scale;
|
||||
|
||||
const Resample_Real NUDGE = 0.5f;
|
||||
xscale = dst_x / (Resample_Real)src_x;
|
||||
|
||||
if (xscale < 1.0f)
|
||||
{
|
||||
int total;
|
||||
(void)total;
|
||||
|
||||
// Handle case when there are fewer destination samples than source samples (downsampling/minification).
|
||||
|
||||
// stretched half width of filter
|
||||
half_width = (filter_support / xscale) * filter_scale;
|
||||
|
||||
// Find the range of source sample(s) that will contribute to each destination sample.
|
||||
|
||||
for (i = 0, n = 0; i < dst_x; i++)
|
||||
{
|
||||
// Convert from discrete to continuous coordinates, scale, then convert back to discrete.
|
||||
center = ((Resample_Real)i + NUDGE) / xscale;
|
||||
center -= NUDGE;
|
||||
center += src_ofs;
|
||||
|
||||
left = cast_to_int((Resample_Real)floor(center - half_width));
|
||||
right = cast_to_int((Resample_Real)ceil(center + half_width));
|
||||
|
||||
Pcontrib_bounds[i].center = center;
|
||||
Pcontrib_bounds[i].left = left;
|
||||
Pcontrib_bounds[i].right = right;
|
||||
|
||||
n += (right - left + 1);
|
||||
}
|
||||
|
||||
// Allocate memory for contributors.
|
||||
|
||||
if ((n == 0) || ((Pcpool = (Contrib*)calloc(n, sizeof(Contrib))) == NULL))
|
||||
{
|
||||
free(Pcontrib);
|
||||
free(Pcontrib_bounds);
|
||||
return NULL;
|
||||
}
|
||||
total = n;
|
||||
|
||||
Pcpool_next = Pcpool;
|
||||
|
||||
// Create the list of source samples which contribute to each destination sample.
|
||||
|
||||
for (i = 0; i < dst_x; i++)
|
||||
{
|
||||
int max_k = -1;
|
||||
Resample_Real max_w = -1e+20f;
|
||||
|
||||
center = Pcontrib_bounds[i].center;
|
||||
left = Pcontrib_bounds[i].left;
|
||||
right = Pcontrib_bounds[i].right;
|
||||
|
||||
Pcontrib[i].n = 0;
|
||||
Pcontrib[i].p = Pcpool_next;
|
||||
Pcpool_next += (right - left + 1);
|
||||
assert((Pcpool_next - Pcpool) <= total);
|
||||
|
||||
total_weight = 0;
|
||||
|
||||
for (j = left; j <= right; j++)
|
||||
total_weight += (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale);
|
||||
const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
|
||||
|
||||
total_weight = 0;
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("%i: ", i);
|
||||
#endif
|
||||
|
||||
for (j = left; j <= right; j++)
|
||||
{
|
||||
weight = (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale) * norm;
|
||||
if (weight == 0.0f)
|
||||
continue;
|
||||
|
||||
n = reflect(j, src_x, boundary_op);
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("%i(%f), ", n, weight);
|
||||
#endif
|
||||
|
||||
// Increment the number of source samples which contribute to the current destination sample.
|
||||
|
||||
k = Pcontrib[i].n++;
|
||||
|
||||
Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
|
||||
Pcontrib[i].p[k].weight = weight; /* store src sample weight */
|
||||
|
||||
total_weight += weight; /* total weight of all contributors */
|
||||
|
||||
if (weight > max_w)
|
||||
{
|
||||
max_w = weight;
|
||||
max_k = k;
|
||||
}
|
||||
}
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
//assert(Pcontrib[i].n);
|
||||
//assert(max_k != -1);
|
||||
if ((max_k == -1) || (Pcontrib[i].n == 0))
|
||||
{
|
||||
free(Pcpool);
|
||||
free(Pcontrib);
|
||||
free(Pcontrib_bounds);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (total_weight != 1.0f)
|
||||
Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle case when there are more destination samples than source samples (upsampling).
|
||||
|
||||
half_width = filter_support * filter_scale;
|
||||
|
||||
// Find the source sample(s) that contribute to each destination sample.
|
||||
|
||||
for (i = 0, n = 0; i < dst_x; i++)
|
||||
{
|
||||
// Convert from discrete to continuous coordinates, scale, then convert back to discrete.
|
||||
center = ((Resample_Real)i + NUDGE) / xscale;
|
||||
center -= NUDGE;
|
||||
center += src_ofs;
|
||||
|
||||
left = cast_to_int((Resample_Real)floor(center - half_width));
|
||||
right = cast_to_int((Resample_Real)ceil(center + half_width));
|
||||
|
||||
Pcontrib_bounds[i].center = center;
|
||||
Pcontrib_bounds[i].left = left;
|
||||
Pcontrib_bounds[i].right = right;
|
||||
|
||||
n += (right - left + 1);
|
||||
}
|
||||
|
||||
/* Allocate memory for contributors. */
|
||||
|
||||
int total = n;
|
||||
if ((total == 0) || ((Pcpool = (Contrib*)calloc(total, sizeof(Contrib))) == NULL))
|
||||
{
|
||||
free(Pcontrib);
|
||||
free(Pcontrib_bounds);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pcpool_next = Pcpool;
|
||||
|
||||
// Create the list of source samples which contribute to each destination sample.
|
||||
|
||||
for (i = 0; i < dst_x; i++)
|
||||
{
|
||||
int max_k = -1;
|
||||
Resample_Real max_w = -1e+20f;
|
||||
|
||||
center = Pcontrib_bounds[i].center;
|
||||
left = Pcontrib_bounds[i].left;
|
||||
right = Pcontrib_bounds[i].right;
|
||||
|
||||
Pcontrib[i].n = 0;
|
||||
Pcontrib[i].p = Pcpool_next;
|
||||
Pcpool_next += (right - left + 1);
|
||||
assert((Pcpool_next - Pcpool) <= total);
|
||||
|
||||
total_weight = 0;
|
||||
for (j = left; j <= right; j++)
|
||||
total_weight += (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale);
|
||||
|
||||
const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
|
||||
|
||||
total_weight = 0;
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("%i: ", i);
|
||||
#endif
|
||||
|
||||
for (j = left; j <= right; j++)
|
||||
{
|
||||
weight = (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale) * norm;
|
||||
if (weight == 0.0f)
|
||||
continue;
|
||||
|
||||
n = reflect(j, src_x, boundary_op);
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("%i(%f), ", n, weight);
|
||||
#endif
|
||||
|
||||
// Increment the number of source samples which contribute to the current destination sample.
|
||||
|
||||
k = Pcontrib[i].n++;
|
||||
|
||||
Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
|
||||
Pcontrib[i].p[k].weight = weight; /* store src sample weight */
|
||||
|
||||
total_weight += weight; /* total weight of all contributors */
|
||||
|
||||
if (weight > max_w)
|
||||
{
|
||||
max_w = weight;
|
||||
max_k = k;
|
||||
}
|
||||
}
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
//assert(Pcontrib[i].n);
|
||||
//assert(max_k != -1);
|
||||
|
||||
if ((max_k == -1) || (Pcontrib[i].n == 0))
|
||||
{
|
||||
free(Pcpool);
|
||||
free(Pcontrib);
|
||||
free(Pcontrib_bounds);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (total_weight != 1.0f)
|
||||
Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
|
||||
}
|
||||
}
|
||||
|
||||
#if RESAMPLER_DEBUG
|
||||
printf("*******\n");
|
||||
#endif
|
||||
|
||||
free(Pcontrib_bounds);
|
||||
|
||||
return Pcontrib;
|
||||
}
|
||||
|
||||
void Resampler::resample_x(Sample * Pdst, const Sample * Psrc)
|
||||
{
|
||||
assert(Pdst);
|
||||
assert(Psrc);
|
||||
|
||||
int i, j;
|
||||
Sample total;
|
||||
Contrib_List* Pclist = m_Pclist_x;
|
||||
Contrib* p;
|
||||
|
||||
for (i = m_resample_dst_x; i > 0; i--, Pclist++)
|
||||
{
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
total_ops += Pclist->n;
|
||||
#endif
|
||||
|
||||
for (j = Pclist->n, p = Pclist->p, total = 0; j > 0; j--, p++)
|
||||
total += Psrc[p->pixel] * p->weight;
|
||||
|
||||
*Pdst++ = total;
|
||||
}
|
||||
}
|
||||
|
||||
void Resampler::scale_y_mov(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
total_ops += dst_x;
|
||||
#endif
|
||||
|
||||
// Not += because temp buf wasn't cleared.
|
||||
for (i = dst_x; i > 0; i--)
|
||||
* Ptmp++ = *Psrc++ * weight;
|
||||
}
|
||||
|
||||
void Resampler::scale_y_add(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
|
||||
{
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
total_ops += dst_x;
|
||||
#endif
|
||||
|
||||
for (int i = dst_x; i > 0; i--)
|
||||
(*Ptmp++) += *Psrc++ * weight;
|
||||
}
|
||||
|
||||
void Resampler::clamp(Sample * Pdst, int n)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
Sample x = *Pdst;
|
||||
*Pdst++ = clamp_sample(x);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
void Resampler::resample_y(Sample * Pdst)
|
||||
{
|
||||
int i, j;
|
||||
Sample* Psrc;
|
||||
Contrib_List* Pclist = &m_Pclist_y[m_cur_dst_y];
|
||||
|
||||
Sample* Ptmp = m_delay_x_resample ? m_Ptmp_buf : Pdst;
|
||||
assert(Ptmp);
|
||||
|
||||
/* Process each contributor. */
|
||||
|
||||
for (i = 0; i < Pclist->n; i++)
|
||||
{
|
||||
// locate the contributor's location in the scan buffer -- the contributor must always be found!
|
||||
for (j = 0; j < MAX_SCAN_BUF_SIZE; j++)
|
||||
if (m_Pscan_buf->scan_buf_y[j] == Pclist->p[i].pixel)
|
||||
break;
|
||||
|
||||
assert(j < MAX_SCAN_BUF_SIZE);
|
||||
|
||||
Psrc = m_Pscan_buf->scan_buf_l[j];
|
||||
|
||||
if (!i)
|
||||
scale_y_mov(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
|
||||
else
|
||||
scale_y_add(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
|
||||
|
||||
/* If this source line doesn't contribute to any
|
||||
* more destination lines then mark the scanline buffer slot
|
||||
* which holds this source line as free.
|
||||
* (The max. number of slots used depends on the Y
|
||||
* axis sampling factor and the scaled filter width.)
|
||||
*/
|
||||
|
||||
if (--m_Psrc_y_count[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] == 0)
|
||||
{
|
||||
m_Psrc_y_flag[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] = false;
|
||||
m_Pscan_buf->scan_buf_y[j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now generate the destination line */
|
||||
|
||||
if (m_delay_x_resample) // Was X resampling delayed until after Y resampling?
|
||||
{
|
||||
assert(Pdst != Ptmp);
|
||||
resample_x(Pdst, Ptmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(Pdst == Ptmp);
|
||||
}
|
||||
|
||||
if (m_lo < m_hi)
|
||||
clamp(Pdst, m_resample_dst_x);
|
||||
}
|
||||
|
||||
bool Resampler::put_line(const Sample * Psrc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (m_cur_src_y >= m_resample_src_y)
|
||||
return false;
|
||||
|
||||
/* Does this source line contribute
|
||||
* to any destination line? if not,
|
||||
* exit now.
|
||||
*/
|
||||
|
||||
if (!m_Psrc_y_count[resampler_range_check(m_cur_src_y, m_resample_src_y)])
|
||||
{
|
||||
m_cur_src_y++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Find an empty slot in the scanline buffer. (FIXME: Perf. is terrible here with extreme scaling ratios.) */
|
||||
|
||||
for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
|
||||
if (m_Pscan_buf->scan_buf_y[i] == -1)
|
||||
break;
|
||||
|
||||
/* If the buffer is full, exit with an error. */
|
||||
|
||||
if (i == MAX_SCAN_BUF_SIZE)
|
||||
{
|
||||
m_status = STATUS_SCAN_BUFFER_FULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Psrc_y_flag[resampler_range_check(m_cur_src_y, m_resample_src_y)] = true;
|
||||
m_Pscan_buf->scan_buf_y[i] = m_cur_src_y;
|
||||
|
||||
/* Does this slot have any memory allocated to it? */
|
||||
|
||||
if (!m_Pscan_buf->scan_buf_l[i])
|
||||
{
|
||||
if ((m_Pscan_buf->scan_buf_l[i] = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Resampling on the X axis first?
|
||||
if (m_delay_x_resample)
|
||||
{
|
||||
assert(m_intermediate_x == m_resample_src_x);
|
||||
|
||||
// Y-X resampling order
|
||||
memcpy(m_Pscan_buf->scan_buf_l[i], Psrc, m_intermediate_x * sizeof(Sample));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_intermediate_x == m_resample_dst_x);
|
||||
|
||||
// X-Y resampling order
|
||||
resample_x(m_Pscan_buf->scan_buf_l[i], Psrc);
|
||||
}
|
||||
|
||||
m_cur_src_y++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Resampler::Sample* Resampler::get_line()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If all the destination lines have been
|
||||
* generated, then always return NULL.
|
||||
*/
|
||||
|
||||
if (m_cur_dst_y == m_resample_dst_y)
|
||||
return NULL;
|
||||
|
||||
/* Check to see if all the required
|
||||
* contributors are present, if not,
|
||||
* return NULL.
|
||||
*/
|
||||
|
||||
for (i = 0; i < m_Pclist_y[m_cur_dst_y].n; i++)
|
||||
if (!m_Psrc_y_flag[resampler_range_check(m_Pclist_y[m_cur_dst_y].p[i].pixel, m_resample_src_y)])
|
||||
return NULL;
|
||||
|
||||
resample_y(m_Pdst_buf);
|
||||
|
||||
m_cur_dst_y++;
|
||||
|
||||
return m_Pdst_buf;
|
||||
}
|
||||
|
||||
Resampler::~Resampler()
|
||||
{
|
||||
int i;
|
||||
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
printf("actual ops: %i\n", total_ops);
|
||||
#endif
|
||||
|
||||
free(m_Pdst_buf);
|
||||
m_Pdst_buf = NULL;
|
||||
|
||||
if (m_Ptmp_buf)
|
||||
{
|
||||
free(m_Ptmp_buf);
|
||||
m_Ptmp_buf = NULL;
|
||||
}
|
||||
|
||||
/* Don't deallocate a contibutor list
|
||||
* if the user passed us one of their own.
|
||||
*/
|
||||
|
||||
if ((m_Pclist_x) && (!m_clist_x_forced))
|
||||
{
|
||||
free(m_Pclist_x->p);
|
||||
free(m_Pclist_x);
|
||||
m_Pclist_x = NULL;
|
||||
}
|
||||
|
||||
if ((m_Pclist_y) && (!m_clist_y_forced))
|
||||
{
|
||||
free(m_Pclist_y->p);
|
||||
free(m_Pclist_y);
|
||||
m_Pclist_y = NULL;
|
||||
}
|
||||
|
||||
free(m_Psrc_y_count);
|
||||
m_Psrc_y_count = NULL;
|
||||
|
||||
free(m_Psrc_y_flag);
|
||||
m_Psrc_y_flag = NULL;
|
||||
|
||||
if (m_Pscan_buf)
|
||||
{
|
||||
for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
|
||||
free(m_Pscan_buf->scan_buf_l[i]);
|
||||
|
||||
free(m_Pscan_buf);
|
||||
m_Pscan_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Resampler::restart()
|
||||
{
|
||||
if (STATUS_OKAY != m_status)
|
||||
return;
|
||||
|
||||
m_cur_src_y = m_cur_dst_y = 0;
|
||||
|
||||
int i, j;
|
||||
for (i = 0; i < m_resample_src_y; i++)
|
||||
{
|
||||
m_Psrc_y_count[i] = 0;
|
||||
m_Psrc_y_flag[i] = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < m_resample_dst_y; i++)
|
||||
{
|
||||
for (j = 0; j < m_Pclist_y[i].n; j++)
|
||||
m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
|
||||
{
|
||||
m_Pscan_buf->scan_buf_y[i] = -1;
|
||||
|
||||
free(m_Pscan_buf->scan_buf_l[i]);
|
||||
m_Pscan_buf->scan_buf_l[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Resampler::Resampler(int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
Boundary_Op boundary_op,
|
||||
Resample_Real sample_low, Resample_Real sample_high,
|
||||
const char* Pfilter_name,
|
||||
Contrib_List * Pclist_x,
|
||||
Contrib_List * Pclist_y,
|
||||
Resample_Real filter_x_scale,
|
||||
Resample_Real filter_y_scale,
|
||||
Resample_Real src_x_ofs,
|
||||
Resample_Real src_y_ofs)
|
||||
{
|
||||
int i, j;
|
||||
Resample_Real support, (*func)(Resample_Real);
|
||||
|
||||
assert(src_x > 0);
|
||||
assert(src_y > 0);
|
||||
assert(dst_x > 0);
|
||||
assert(dst_y > 0);
|
||||
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
total_ops = 0;
|
||||
#endif
|
||||
|
||||
m_lo = sample_low;
|
||||
m_hi = sample_high;
|
||||
|
||||
m_delay_x_resample = false;
|
||||
m_intermediate_x = 0;
|
||||
m_Pdst_buf = NULL;
|
||||
m_Ptmp_buf = NULL;
|
||||
m_clist_x_forced = false;
|
||||
m_Pclist_x = NULL;
|
||||
m_clist_y_forced = false;
|
||||
m_Pclist_y = NULL;
|
||||
m_Psrc_y_count = NULL;
|
||||
m_Psrc_y_flag = NULL;
|
||||
m_Pscan_buf = NULL;
|
||||
m_status = STATUS_OKAY;
|
||||
|
||||
m_resample_src_x = src_x;
|
||||
m_resample_src_y = src_y;
|
||||
m_resample_dst_x = dst_x;
|
||||
m_resample_dst_y = dst_y;
|
||||
|
||||
m_boundary_op = boundary_op;
|
||||
|
||||
if ((m_Pdst_buf = (Sample*)malloc(m_resample_dst_x * sizeof(Sample))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the specified filter.
|
||||
|
||||
if (Pfilter_name == NULL)
|
||||
Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER;
|
||||
|
||||
for (i = 0; i < g_num_resample_filters; i++)
|
||||
if (strcmp(Pfilter_name, g_resample_filters[i].name) == 0)
|
||||
break;
|
||||
|
||||
if (i == g_num_resample_filters)
|
||||
{
|
||||
m_status = STATUS_BAD_FILTER_NAME;
|
||||
return;
|
||||
}
|
||||
|
||||
func = g_resample_filters[i].func;
|
||||
support = g_resample_filters[i].support;
|
||||
|
||||
/* Create contributor lists, unless the user supplied custom lists. */
|
||||
|
||||
if (!Pclist_x)
|
||||
{
|
||||
m_Pclist_x = make_clist(m_resample_src_x, m_resample_dst_x, m_boundary_op, func, support, filter_x_scale, src_x_ofs);
|
||||
if (!m_Pclist_x)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Pclist_x = Pclist_x;
|
||||
m_clist_x_forced = true;
|
||||
}
|
||||
|
||||
if (!Pclist_y)
|
||||
{
|
||||
m_Pclist_y = make_clist(m_resample_src_y, m_resample_dst_y, m_boundary_op, func, support, filter_y_scale, src_y_ofs);
|
||||
if (!m_Pclist_y)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Pclist_y = Pclist_y;
|
||||
m_clist_y_forced = true;
|
||||
}
|
||||
|
||||
if ((m_Psrc_y_count = (int*)calloc(m_resample_src_y, sizeof(int))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_Psrc_y_flag = (unsigned char*)calloc(m_resample_src_y, sizeof(unsigned char))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// Count how many times each source line contributes to a destination line.
|
||||
|
||||
for (i = 0; i < m_resample_dst_y; i++)
|
||||
for (j = 0; j < m_Pclist_y[i].n; j++)
|
||||
m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
|
||||
|
||||
if ((m_Pscan_buf = (Scan_Buf*)malloc(sizeof(Scan_Buf))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
|
||||
{
|
||||
m_Pscan_buf->scan_buf_y[i] = -1;
|
||||
m_Pscan_buf->scan_buf_l[i] = NULL;
|
||||
}
|
||||
|
||||
m_cur_src_y = m_cur_dst_y = 0;
|
||||
{
|
||||
// Determine which axis to resample first by comparing the number of multiplies required
|
||||
// for each possibility.
|
||||
int x_ops = count_ops(m_Pclist_x, m_resample_dst_x);
|
||||
int y_ops = count_ops(m_Pclist_y, m_resample_dst_y);
|
||||
|
||||
// Hack 10/2000: Weight Y axis ops a little more than X axis ops.
|
||||
// (Y axis ops use more cache resources.)
|
||||
int xy_ops = x_ops * m_resample_src_y +
|
||||
(4 * y_ops * m_resample_dst_x) / 3;
|
||||
|
||||
int yx_ops = (4 * y_ops * m_resample_src_x) / 3 +
|
||||
x_ops * m_resample_dst_y;
|
||||
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
printf("src: %i %i\n", m_resample_src_x, m_resample_src_y);
|
||||
printf("dst: %i %i\n", m_resample_dst_x, m_resample_dst_y);
|
||||
printf("x_ops: %i\n", x_ops);
|
||||
printf("y_ops: %i\n", y_ops);
|
||||
printf("xy_ops: %i\n", xy_ops);
|
||||
printf("yx_ops: %i\n", yx_ops);
|
||||
#endif
|
||||
|
||||
// Now check which resample order is better. In case of a tie, choose the order
|
||||
// which buffers the least amount of data.
|
||||
if ((xy_ops > yx_ops) ||
|
||||
((xy_ops == yx_ops) && (m_resample_src_x < m_resample_dst_x)))
|
||||
{
|
||||
m_delay_x_resample = true;
|
||||
m_intermediate_x = m_resample_src_x;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_delay_x_resample = false;
|
||||
m_intermediate_x = m_resample_dst_x;
|
||||
}
|
||||
#if BASISU_RESAMPLER_DEBUG_OPS
|
||||
printf("delaying: %i\n", m_delay_x_resample);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m_delay_x_resample)
|
||||
{
|
||||
if ((m_Ptmp_buf = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
|
||||
{
|
||||
m_status = STATUS_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resampler::get_clists(Contrib_List * *ptr_clist_x, Contrib_List * *ptr_clist_y)
|
||||
{
|
||||
if (ptr_clist_x)
|
||||
* ptr_clist_x = m_Pclist_x;
|
||||
|
||||
if (ptr_clist_y)
|
||||
* ptr_clist_y = m_Pclist_y;
|
||||
}
|
||||
|
||||
int Resampler::get_filter_num()
|
||||
{
|
||||
return g_num_resample_filters;
|
||||
}
|
||||
|
||||
const char* Resampler::get_filter_name(int filter_num)
|
||||
{
|
||||
if ((filter_num < 0) || (filter_num >= g_num_resample_filters))
|
||||
return NULL;
|
||||
else
|
||||
return g_resample_filters[filter_num].name;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
// basisu_resampler.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "../transcoder/basisu.h"
|
||||
|
||||
#define BASISU_RESAMPLER_DEBUG_OPS (0)
|
||||
#define BASISU_RESAMPLER_DEFAULT_FILTER "lanczos4"
|
||||
#define BASISU_RESAMPLER_MAX_DIMENSION (16384)
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
// float or double
|
||||
typedef float Resample_Real;
|
||||
|
||||
class Resampler
|
||||
{
|
||||
public:
|
||||
typedef Resample_Real Sample;
|
||||
|
||||
struct Contrib
|
||||
{
|
||||
Resample_Real weight;
|
||||
uint16_t pixel;
|
||||
};
|
||||
|
||||
struct Contrib_List
|
||||
{
|
||||
uint16_t n;
|
||||
Contrib *p;
|
||||
};
|
||||
|
||||
enum Boundary_Op
|
||||
{
|
||||
BOUNDARY_WRAP = 0,
|
||||
BOUNDARY_REFLECT = 1,
|
||||
BOUNDARY_CLAMP = 2
|
||||
};
|
||||
|
||||
enum Status
|
||||
{
|
||||
STATUS_OKAY = 0,
|
||||
STATUS_OUT_OF_MEMORY = 1,
|
||||
STATUS_BAD_FILTER_NAME = 2,
|
||||
STATUS_SCAN_BUFFER_FULL = 3
|
||||
};
|
||||
|
||||
// src_x/src_y - Input dimensions
|
||||
// dst_x/dst_y - Output dimensions
|
||||
// boundary_op - How to sample pixels near the image boundaries
|
||||
// sample_low/sample_high - Clamp output samples to specified range, or disable clamping if sample_low >= sample_high
|
||||
// Pclist_x/Pclist_y - Optional pointers to contributor lists from another instance of a Resampler
|
||||
// src_x_ofs/src_y_ofs - Offset input image by specified amount (fractional values okay)
|
||||
Resampler(
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
Boundary_Op boundary_op = BOUNDARY_CLAMP,
|
||||
Resample_Real sample_low = 0.0f, Resample_Real sample_high = 0.0f,
|
||||
const char *Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER,
|
||||
Contrib_List *Pclist_x = NULL,
|
||||
Contrib_List *Pclist_y = NULL,
|
||||
Resample_Real filter_x_scale = 1.0f,
|
||||
Resample_Real filter_y_scale = 1.0f,
|
||||
Resample_Real src_x_ofs = 0.0f,
|
||||
Resample_Real src_y_ofs = 0.0f);
|
||||
|
||||
~Resampler();
|
||||
|
||||
// Reinits resampler so it can handle another frame.
|
||||
void restart();
|
||||
|
||||
// false on out of memory.
|
||||
bool put_line(const Sample *Psrc);
|
||||
|
||||
// NULL if no scanlines are currently available (give the resampler more scanlines!)
|
||||
const Sample *get_line();
|
||||
|
||||
Status status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
// Returned contributor lists can be shared with another Resampler.
|
||||
void get_clists(Contrib_List **ptr_clist_x, Contrib_List **ptr_clist_y);
|
||||
Contrib_List *get_clist_x() const
|
||||
{
|
||||
return m_Pclist_x;
|
||||
}
|
||||
Contrib_List *get_clist_y() const
|
||||
{
|
||||
return m_Pclist_y;
|
||||
}
|
||||
|
||||
// Filter accessors.
|
||||
static int get_filter_num();
|
||||
static const char *get_filter_name(int filter_num);
|
||||
|
||||
static Contrib_List *make_clist(
|
||||
int src_x, int dst_x, Boundary_Op boundary_op,
|
||||
Resample_Real(*Pfilter)(Resample_Real),
|
||||
Resample_Real filter_support,
|
||||
Resample_Real filter_scale,
|
||||
Resample_Real src_ofs);
|
||||
|
||||
private:
|
||||
Resampler();
|
||||
Resampler(const Resampler &o);
|
||||
Resampler &operator=(const Resampler &o);
|
||||
|
||||
#ifdef BASISU_RESAMPLER_DEBUG_OPS
|
||||
int total_ops;
|
||||
#endif
|
||||
|
||||
int m_intermediate_x;
|
||||
|
||||
int m_resample_src_x;
|
||||
int m_resample_src_y;
|
||||
int m_resample_dst_x;
|
||||
int m_resample_dst_y;
|
||||
|
||||
Boundary_Op m_boundary_op;
|
||||
|
||||
Sample *m_Pdst_buf;
|
||||
Sample *m_Ptmp_buf;
|
||||
|
||||
Contrib_List *m_Pclist_x;
|
||||
Contrib_List *m_Pclist_y;
|
||||
|
||||
bool m_clist_x_forced;
|
||||
bool m_clist_y_forced;
|
||||
|
||||
bool m_delay_x_resample;
|
||||
|
||||
int *m_Psrc_y_count;
|
||||
uint8_t *m_Psrc_y_flag;
|
||||
|
||||
// The maximum number of scanlines that can be buffered at one time.
|
||||
enum
|
||||
{
|
||||
MAX_SCAN_BUF_SIZE = BASISU_RESAMPLER_MAX_DIMENSION
|
||||
};
|
||||
|
||||
struct Scan_Buf
|
||||
{
|
||||
int scan_buf_y[MAX_SCAN_BUF_SIZE];
|
||||
Sample *scan_buf_l[MAX_SCAN_BUF_SIZE];
|
||||
};
|
||||
|
||||
Scan_Buf *m_Pscan_buf;
|
||||
|
||||
int m_cur_src_y;
|
||||
int m_cur_dst_y;
|
||||
|
||||
Status m_status;
|
||||
|
||||
void resample_x(Sample *Pdst, const Sample *Psrc);
|
||||
void scale_y_mov(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
|
||||
void scale_y_add(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
|
||||
void clamp(Sample *Pdst, int n);
|
||||
void resample_y(Sample *Pdst);
|
||||
|
||||
static int reflect(const int j, const int src_x, const Boundary_Op boundary_op);
|
||||
|
||||
inline int count_ops(Contrib_List *Pclist, int k)
|
||||
{
|
||||
int i, t = 0;
|
||||
for (i = 0; i < k; i++)
|
||||
t += Pclist[i].n;
|
||||
return (t);
|
||||
}
|
||||
|
||||
Resample_Real m_lo;
|
||||
Resample_Real m_hi;
|
||||
|
||||
inline Resample_Real clamp_sample(Resample_Real f) const
|
||||
{
|
||||
if (f < m_lo)
|
||||
f = m_lo;
|
||||
else if (f > m_hi)
|
||||
f = m_hi;
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
@@ -0,0 +1,35 @@
|
||||
// basisu_resampler_filters.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include "../transcoder/basisu.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
typedef float (*resample_filter_func)(float t);
|
||||
|
||||
struct resample_filter
|
||||
{
|
||||
const char *name;
|
||||
resample_filter_func func;
|
||||
float support;
|
||||
};
|
||||
|
||||
extern const resample_filter g_resample_filters[];
|
||||
extern const int g_num_resample_filters;
|
||||
|
||||
int find_resample_filter(const char *pName);
|
||||
|
||||
} // namespace basisu
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
// basisu_ssim.cpp
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_ssim.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
float gauss(int x, int y, float sigma_sqr)
|
||||
{
|
||||
float pow = expf(-((x * x + y * y) / (2.0f * sigma_sqr)));
|
||||
float g = (1.0f / (sqrtf((float)(2.0f * M_PI * sigma_sqr)))) * pow;
|
||||
return g;
|
||||
}
|
||||
|
||||
// size_x/y should be odd
|
||||
void compute_gaussian_kernel(float *pDst, int size_x, int size_y, float sigma_sqr, uint32_t flags)
|
||||
{
|
||||
assert(size_x & size_y & 1);
|
||||
|
||||
if (!(size_x | size_y))
|
||||
return;
|
||||
|
||||
int mid_x = size_x / 2;
|
||||
int mid_y = size_y / 2;
|
||||
|
||||
double sum = 0;
|
||||
for (int x = 0; x < size_x; x++)
|
||||
{
|
||||
for (int y = 0; y < size_y; y++)
|
||||
{
|
||||
float g;
|
||||
if ((x > mid_x) && (y < mid_y))
|
||||
g = pDst[(size_x - x - 1) + y * size_x];
|
||||
else if ((x < mid_x) && (y > mid_y))
|
||||
g = pDst[x + (size_y - y - 1) * size_x];
|
||||
else if ((x > mid_x) && (y > mid_y))
|
||||
g = pDst[(size_x - x - 1) + (size_y - y - 1) * size_x];
|
||||
else
|
||||
g = gauss(x - mid_x, y - mid_y, sigma_sqr);
|
||||
|
||||
pDst[x + y * size_x] = g;
|
||||
sum += g;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & cComputeGaussianFlagNormalizeCenterToOne)
|
||||
{
|
||||
sum = pDst[mid_x + mid_y * size_x];
|
||||
}
|
||||
|
||||
if (flags & (cComputeGaussianFlagNormalizeCenterToOne | cComputeGaussianFlagNormalize))
|
||||
{
|
||||
double one_over_sum = 1.0f / sum;
|
||||
for (int i = 0; i < size_x * size_y; i++)
|
||||
pDst[i] = static_cast<float>(pDst[i] * one_over_sum);
|
||||
|
||||
if (flags & cComputeGaussianFlagNormalizeCenterToOne)
|
||||
pDst[mid_x + mid_y * size_x] = 1.0f;
|
||||
}
|
||||
|
||||
if (flags & cComputeGaussianFlagPrint)
|
||||
{
|
||||
printf("{\n");
|
||||
for (int y = 0; y < size_y; y++)
|
||||
{
|
||||
printf(" ");
|
||||
for (int x = 0; x < size_x; x++)
|
||||
{
|
||||
printf("%f, ", pDst[x + y * size_x]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
}
|
||||
|
||||
void gaussian_filter(imagef &dst, const imagef &orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping, uint32_t width_divisor, uint32_t height_divisor)
|
||||
{
|
||||
assert(odd_filter_width && (odd_filter_width & 1));
|
||||
odd_filter_width |= 1;
|
||||
|
||||
vector2D<float> kernel(odd_filter_width, odd_filter_width);
|
||||
compute_gaussian_kernel(kernel.get_ptr(), odd_filter_width, odd_filter_width, sigma_sqr, cComputeGaussianFlagNormalize);
|
||||
|
||||
const int dst_width = orig_img.get_width() / width_divisor;
|
||||
const int dst_height = orig_img.get_height() / height_divisor;
|
||||
|
||||
const int H = odd_filter_width / 2;
|
||||
const int L = -H;
|
||||
|
||||
dst.crop(dst_width, dst_height);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int oy = 0; oy < dst_height; oy++)
|
||||
{
|
||||
for (int ox = 0; ox < dst_width; ox++)
|
||||
{
|
||||
vec4F c(0.0f);
|
||||
|
||||
for (int yd = L; yd <= H; yd++)
|
||||
{
|
||||
int y = oy * height_divisor + (height_divisor >> 1) + yd;
|
||||
|
||||
for (int xd = L; xd <= H; xd++)
|
||||
{
|
||||
int x = ox * width_divisor + (width_divisor >> 1) + xd;
|
||||
|
||||
const vec4F &p = orig_img.get_clamped_or_wrapped(x, y, wrapping, wrapping);
|
||||
|
||||
float w = kernel(xd + H, yd + H);
|
||||
c[0] += p[0] * w;
|
||||
c[1] += p[1] * w;
|
||||
c[2] += p[2] * w;
|
||||
c[3] += p[3] * w;
|
||||
}
|
||||
}
|
||||
|
||||
dst(ox, oy).set(c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pow_image(const imagef &src, imagef &dst, const vec4F &power)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &p = src(x, y);
|
||||
|
||||
if ((power[0] == 2.0f) && (power[1] == 2.0f) && (power[2] == 2.0f) && (power[3] == 2.0f))
|
||||
dst(x, y).set(p[0] * p[0], p[1] * p[1], p[2] * p[2], p[3] * p[3]);
|
||||
else
|
||||
dst(x, y).set(powf(p[0], power[0]), powf(p[1], power[1]), powf(p[2], power[2]), powf(p[3], power[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mul_image(const imagef &src, imagef &dst, const vec4F &mul)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &p = src(x, y);
|
||||
dst(x, y).set(p[0] * mul[0], p[1] * mul[1], p[2] * mul[2], p[3] * mul[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scale_image(const imagef &src, imagef &dst, const vec4F &scale, const vec4F &shift)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &p = src(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
d[c] = scale[c] * p[c] + shift[c];
|
||||
|
||||
dst(x, y).set(d[0], d[1], d[2], d[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_weighted_image(const imagef &src1, const vec4F &alpha, const imagef &src2, const vec4F &beta, const vec4F &gamma, imagef &dst)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &s1 = src1(x, y);
|
||||
const vec4F &s2 = src2(x, y);
|
||||
|
||||
dst(x, y).set(
|
||||
s1[0] * alpha[0] + s2[0] * beta[0] + gamma[0],
|
||||
s1[1] * alpha[1] + s2[1] * beta[1] + gamma[1],
|
||||
s1[2] * alpha[2] + s2[2] * beta[2] + gamma[2],
|
||||
s1[3] * alpha[3] + s2[3] * beta[3] + gamma[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_image(const imagef &src1, const imagef &src2, imagef &dst)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &s1 = src1(x, y);
|
||||
const vec4F &s2 = src2(x, y);
|
||||
|
||||
dst(x, y).set(s1[0] + s2[0], s1[1] + s2[1], s1[2] + s2[2], s1[3] + s2[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adds_image(const imagef &src, const vec4F &value, imagef &dst)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &p = src(x, y);
|
||||
|
||||
dst(x, y).set(p[0] + value[0], p[1] + value[1], p[2] + value[2], p[3] + value[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mul_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &s1 = src1(x, y);
|
||||
const vec4F &s2 = src2(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
float v1 = s1[c];
|
||||
float v2 = s2[c];
|
||||
d[c] = v1 * v2 * scale[c];
|
||||
}
|
||||
|
||||
dst(x, y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void div_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F &s1 = src1(x, y);
|
||||
const vec4F &s2 = src2(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
float v = s2[c];
|
||||
if (v == 0.0f)
|
||||
d[c] = 0.0f;
|
||||
else
|
||||
d[c] = (s1[c] * scale[c]) / v;
|
||||
}
|
||||
|
||||
dst(x, y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec4F avg_image(const imagef &src)
|
||||
{
|
||||
vec4F avg(0.0f);
|
||||
|
||||
for (uint32_t y = 0; y < src.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < src.get_width(); x++)
|
||||
{
|
||||
const vec4F &s = src(x, y);
|
||||
|
||||
avg += vec4F(s[0], s[1], s[2], s[3]);
|
||||
}
|
||||
}
|
||||
|
||||
avg /= static_cast<float>(src.get_total_pixels());
|
||||
|
||||
return avg;
|
||||
}
|
||||
|
||||
// Reference: https://ece.uwaterloo.ca/~z70wang/research/ssim/index.html
|
||||
vec4F compute_ssim(const imagef &a, const imagef &b)
|
||||
{
|
||||
imagef axb, a_sq, b_sq, mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, s1_sq, s2_sq, s12, smap, t1, t2, t3;
|
||||
|
||||
const float C1 = 6.50250f, C2 = 58.52250f;
|
||||
|
||||
pow_image(a, a_sq, vec4F(2));
|
||||
pow_image(b, b_sq, vec4F(2));
|
||||
mul_image(a, b, axb, vec4F(1.0f));
|
||||
|
||||
gaussian_filter(mu1, a, 11, 1.5f * 1.5f);
|
||||
gaussian_filter(mu2, b, 11, 1.5f * 1.5f);
|
||||
|
||||
pow_image(mu1, mu1_sq, vec4F(2));
|
||||
pow_image(mu2, mu2_sq, vec4F(2));
|
||||
mul_image(mu1, mu2, mu1_mu2, vec4F(1.0f));
|
||||
|
||||
gaussian_filter(s1_sq, a_sq, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s1_sq, vec4F(1), mu1_sq, vec4F(-1), vec4F(0), s1_sq);
|
||||
|
||||
gaussian_filter(s2_sq, b_sq, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s2_sq, vec4F(1), mu2_sq, vec4F(-1), vec4F(0), s2_sq);
|
||||
|
||||
gaussian_filter(s12, axb, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s12, vec4F(1), mu1_mu2, vec4F(-1), vec4F(0), s12);
|
||||
|
||||
scale_image(mu1_mu2, t1, vec4F(2), vec4F(0));
|
||||
adds_image(t1, vec4F(C1), t1);
|
||||
|
||||
scale_image(s12, t2, vec4F(2), vec4F(0));
|
||||
adds_image(t2, vec4F(C2), t2);
|
||||
|
||||
mul_image(t1, t2, t3, vec4F(1));
|
||||
|
||||
add_image(mu1_sq, mu2_sq, t1);
|
||||
adds_image(t1, vec4F(C1), t1);
|
||||
|
||||
add_image(s1_sq, s2_sq, t2);
|
||||
adds_image(t2, vec4F(C2), t2);
|
||||
|
||||
mul_image(t1, t2, t1, vec4F(1));
|
||||
|
||||
div_image(t3, t1, smap, vec4F(1));
|
||||
|
||||
return avg_image(smap);
|
||||
}
|
||||
|
||||
vec4F compute_ssim(const image &a, const image &b, bool luma, bool luma_601)
|
||||
{
|
||||
image ta(a), tb(b);
|
||||
|
||||
if ((ta.get_width() != tb.get_width()) || (ta.get_height() != tb.get_height()))
|
||||
{
|
||||
debug_printf("compute_ssim: Cropping input images to equal dimensions\n");
|
||||
|
||||
const uint32_t w = minimum(a.get_width(), b.get_width());
|
||||
const uint32_t h = minimum(a.get_height(), b.get_height());
|
||||
ta.crop(w, h);
|
||||
tb.crop(w, h);
|
||||
}
|
||||
|
||||
if (!ta.get_width() || !ta.get_height())
|
||||
{
|
||||
assert(0);
|
||||
return vec4F(0);
|
||||
}
|
||||
|
||||
if (luma)
|
||||
{
|
||||
for (uint32_t y = 0; y < ta.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < ta.get_width(); x++)
|
||||
{
|
||||
ta(x, y).set(ta(x, y).get_luma(luma_601), ta(x, y).a);
|
||||
tb(x, y).set(tb(x, y).get_luma(luma_601), tb(x, y).a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imagef fta, ftb;
|
||||
|
||||
fta.set(ta);
|
||||
ftb.set(tb);
|
||||
|
||||
return compute_ssim(fta, ftb);
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// basisu_ssim.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
float gauss(int x, int y, float sigma_sqr);
|
||||
|
||||
enum
|
||||
{
|
||||
cComputeGaussianFlagNormalize = 1,
|
||||
cComputeGaussianFlagPrint = 2,
|
||||
cComputeGaussianFlagNormalizeCenterToOne = 4
|
||||
};
|
||||
|
||||
void compute_gaussian_kernel(float *pDst, int size_x, int size_y, float sigma_sqr, uint32_t flags = 0);
|
||||
|
||||
void scale_image(const imagef &src, imagef &dst, const vec4F &scale, const vec4F &shift);
|
||||
void add_weighted_image(const imagef &src1, const vec4F &alpha, const imagef &src2, const vec4F &beta, const vec4F &gamma, imagef &dst);
|
||||
void add_image(const imagef &src1, const imagef &src2, imagef &dst);
|
||||
void adds_image(const imagef &src, const vec4F &value, imagef &dst);
|
||||
void mul_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale);
|
||||
void div_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale);
|
||||
vec4F avg_image(const imagef &src);
|
||||
|
||||
void gaussian_filter(imagef &dst, const imagef &orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping = false, uint32_t width_divisor = 1, uint32_t height_divisor = 1);
|
||||
|
||||
vec4F compute_ssim(const imagef &a, const imagef &b);
|
||||
vec4F compute_ssim(const image &a, const image &b, bool luma, bool luma_601);
|
||||
|
||||
} // namespace basisu
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user