mirror of
https://github.com/drewcassidy/quicktex.git
synced 2024-09-13 06:37:34 +00:00
Merge branch 'dev'
This commit is contained in:
commit
4cdcb65f3a
12
.github/workflows/python-package.yml
vendored
12
.github/workflows/python-package.yml
vendored
@ -16,7 +16,9 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v3.1.2
|
uses: actions/setup-python@v4.3.0
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -70,13 +72,13 @@ jobs:
|
|||||||
|
|
||||||
- name: Install QEMU
|
- name: Install QEMU
|
||||||
# install QEMU if building for arm linux
|
# install QEMU if building for arm linux
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v2
|
||||||
if: runner.os == 'linux' && matrix.arch[3] == 'aarch64'
|
if: runner.os == 'linux' && matrix.arch[3] == 'aarch64'
|
||||||
with:
|
with:
|
||||||
platforms: arm64
|
platforms: arm64
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@2.5.0
|
uses: pypa/cibuildwheel@v2.11.2
|
||||||
env:
|
env:
|
||||||
MACOSX_DEPLOYMENT_TARGET: "10.15"
|
MACOSX_DEPLOYMENT_TARGET: "10.15"
|
||||||
CIBW_ARCHS_LINUX: ${{ matrix.arch[3] }}
|
CIBW_ARCHS_LINUX: ${{ matrix.arch[3] }}
|
||||||
@ -96,7 +98,9 @@ jobs:
|
|||||||
- uses: actions/checkout@v3 # just need the changelog
|
- uses: actions/checkout@v3 # just need the changelog
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v3.1.2
|
uses: actions/setup-python@v4.3.0
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file
|
All notable changes to this project will be documented in this file
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated Pybind11 to version 3.10, adding Python 3.11 support
|
||||||
|
|
||||||
|
|
||||||
## 0.1.3 - 2022-04-13
|
## 0.1.3 - 2022-04-13
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.18)
|
||||||
include(CheckIPOSupported)
|
|
||||||
include(tools/CompilerWarnings.cmake)
|
include(tools/CompilerWarnings.cmake)
|
||||||
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
|
|
||||||
project(quicktex)
|
project(quicktex)
|
||||||
|
|
||||||
@ -30,8 +30,6 @@ file(GLOB HEADER_FILES
|
|||||||
"quicktex/s3tc/interpolator/*.h"
|
"quicktex/s3tc/interpolator/*.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB TEST_FILES "tests/*.cpp")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE PYTHON_FILES "src/**/*.py")
|
file(GLOB_RECURSE PYTHON_FILES "src/**/*.py")
|
||||||
|
|
||||||
# Organize source files together for some IDEs
|
# Organize source files together for some IDEs
|
||||||
@ -42,34 +40,24 @@ pybind11_add_module(_quicktex
|
|||||||
${SOURCE_FILES}
|
${SOURCE_FILES}
|
||||||
${HEADER_FILES})
|
${HEADER_FILES})
|
||||||
|
|
||||||
add_executable(test_quicktex
|
# Set Quicktex version info
|
||||||
${SOURCE_FILES}
|
|
||||||
${HEADER_FILES}
|
|
||||||
${TEST_FILES})
|
|
||||||
|
|
||||||
target_link_libraries(test_quicktex PRIVATE pybind11::embed)
|
|
||||||
|
|
||||||
target_compile_definitions(test_quicktex PRIVATE -DCUSTOM_SYS_PATH="${CMAKE_HOME_DIRECTORY}/env/lib/python3.9/site-packages")
|
|
||||||
target_compile_definitions(_quicktex PRIVATE VERSION_INFO=${QUICKTEX_VERSION_INFO})
|
target_compile_definitions(_quicktex PRIVATE VERSION_INFO=${QUICKTEX_VERSION_INFO})
|
||||||
|
|
||||||
# enable openMP if available
|
# enable openMP if available
|
||||||
if (OpenMP_CXX_FOUND)
|
if (OpenMP_CXX_FOUND)
|
||||||
target_link_libraries(_quicktex PUBLIC OpenMP::OpenMP_CXX)
|
target_link_libraries(_quicktex PUBLIC OpenMP::OpenMP_CXX)
|
||||||
target_link_libraries(test_quicktex PUBLIC OpenMP::OpenMP_CXX)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Set module features, like C/C++ standards
|
# Set module features, like C/C++ standards
|
||||||
target_compile_features(_quicktex PUBLIC cxx_std_17 c_std_11)
|
target_compile_features(_quicktex PUBLIC cxx_std_17 c_std_11)
|
||||||
target_compile_features(test_quicktex PUBLIC cxx_std_17 c_std_11)
|
|
||||||
|
|
||||||
|
# Set compiler warnings
|
||||||
set_project_warnings(_quicktex)
|
set_project_warnings(_quicktex)
|
||||||
set_project_warnings(test_quicktex)
|
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
|
|
||||||
|
# Clang-specific
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlib=libc++ -fsanitize=undefined")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlib=libc++ -fsanitize=undefined")
|
||||||
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
|
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
|
||||||
endif ()
|
endif ()
|
||||||
|
25
DEVELOPMENT.md
Normal file
25
DEVELOPMENT.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Development
|
||||||
|
|
||||||
|
This document outlines how to set up a development environment for Quicktex. Documentation on writing Python extension modules is sparse, so I hope this document is useful for other projects as well. The [Coding Patterns for Python Extensions](https://pythonextensionpatterns.readthedocs.io/en/latest/) site has some useful information and will be linked to often in this document.
|
||||||
|
|
||||||
|
## Setting up Debug Python
|
||||||
|
|
||||||
|
Many development tools require debug symbols to function, and since the front-end for accessing an extension module is Python, that usually means adding debug symbols to Python. [This Page](https://pythonextensionpatterns.readthedocs.io/en/latest/debugging/debug_python.html) has some instructions on building python with debug symbols.
|
||||||
|
|
||||||
|
If you plan to use DTrace, enable the `--with-dtrace` flag when running `configure`.
|
||||||
|
|
||||||
|
It's useful for this debug python to have SSL enabled so that packages can be installed using pip. Enable SSL with the `--with-openssl` flag when running `configure`. If you are on macOS and installed OpenSSL through Homebrew, you may need to use `--with-openssl=$(brew --prefix openssl)` to help the compiler find it.
|
||||||
|
|
||||||
|
### Installing Debug Python
|
||||||
|
|
||||||
|
You can keep the resulting binary in your local copy of the cpython repo and symlink to it, but I like to install it somewhere like `/opt/python-debug/`. The install location is set in the `configure` tool using the `--prefix` flag, and installation is done by running `make install`
|
||||||
|
|
||||||
|
### Mixing Debug and Release Python
|
||||||
|
|
||||||
|
The debug build of python is slow (It may be possible to build with debug symbols but full optimization, I have not looked into it). If you already have a venv setup for your project, you can just symlink the debug python binary into `env/bin` with a full name like `python3.9d`. Make sure that the debug build has the same minor version (e.g '3.9') as the version you made the virtual environment with to maintain ABI compatibility.
|
||||||
|
|
||||||
|
## Profiling with Dtrace
|
||||||
|
|
||||||
|
DTrace is the default program profiler on macOS and other Unix systems, but it's also available for use on Windows and Linux. Using DTrace requires building Python with DTrace hooks as seen above.
|
||||||
|
|
||||||
|
Your extension module does not need a full debug build to profile, but it does need frame pointers to see the stack trace at each sample, as well as debug symbols to give functions names. The cmake build type `RelWithDebInfo` handles this automatically.
|
2
docs/development.md
Normal file
2
docs/development.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
```{include} ../DEVELOPMENT.md
|
||||||
|
```
|
@ -23,6 +23,7 @@ reference/index
|
|||||||
maxdepth: 1
|
maxdepth: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
development
|
||||||
Changelog <changelog>
|
Changelog <changelog>
|
||||||
License <license>
|
License <license>
|
||||||
```
|
```
|
||||||
|
@ -4,7 +4,7 @@ requires = [
|
|||||||
"setuptools_scm>=6.2",
|
"setuptools_scm>=6.2",
|
||||||
"wheel",
|
"wheel",
|
||||||
"cmake>=3.18",
|
"cmake>=3.18",
|
||||||
"pybind11~=2.6.1",
|
"pybind11~=2.10",
|
||||||
"ninja; sys_platform != 'win32'",
|
"ninja; sys_platform != 'win32'",
|
||||||
]
|
]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
@ -36,7 +36,7 @@ dependencies = ["Pillow", "click"]
|
|||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
tests = ["parameterized"]
|
tests = ["parameterized", "pytest"]
|
||||||
docs = [
|
docs = [
|
||||||
"Sphinx >= 3.5",
|
"Sphinx >= 3.5",
|
||||||
"sphinx-click >= 2.7",
|
"sphinx-click >= 2.7",
|
||||||
@ -64,7 +64,7 @@ package-dir = { '' = '.' } # without this line, C++ source files get included in
|
|||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
build = "cp*" # only build wheels for cpython.
|
build = "cp*" # only build wheels for cpython.
|
||||||
build-frontend = "build"
|
build-frontend = "build"
|
||||||
test-command = "cd {project} && python -m unittest --verbose"
|
test-command = "pytest {project}/tests --verbose"
|
||||||
test-extras = ["tests"]
|
test-extras = ["tests"]
|
||||||
|
|
||||||
[tool.cibuildwheel.macos]
|
[tool.cibuildwheel.macos]
|
||||||
@ -73,7 +73,6 @@ skip = ["cp{38,39,31*}-macosx_x86_64"] # skip x86-only builds where fat binaries
|
|||||||
|
|
||||||
[tool.cibuildwheel.windows]
|
[tool.cibuildwheel.windows]
|
||||||
archs = ["auto64"] # arm64 windows builds not yet supported
|
archs = ["auto64"] # arm64 windows builds not yet supported
|
||||||
test-command = "cd /d {project} && python -m unittest --verbose" # windows why is this flag required
|
|
||||||
|
|
||||||
[tool.cibuildwheel.linux]
|
[tool.cibuildwheel.linux]
|
||||||
skip = ["cp37-musllinux*", "*musllinux_aarch64*"] # skip targets without available Pillow wheels
|
skip = ["cp37-musllinux*", "*musllinux_aarch64*"] # skip targets without available Pillow wheels
|
||||||
@ -82,5 +81,5 @@ manylinux-aarch64-image = "manylinux2014"
|
|||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 120 # 80-column is stupid
|
line-length = 120 # 80-column is stupid
|
||||||
target-version = ['py37', 'py38', 'py39', 'py310']
|
target-version = ['py37', 'py38', 'py39', 'py310', 'py310']
|
||||||
skip-string-normalization = true
|
skip-string-normalization = true
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ template <size_t N> class OrderTable {
|
|||||||
static bool Generate() {
|
static bool Generate() {
|
||||||
static_assert(N == 4 || N == 3);
|
static_assert(N == 4 || N == 3);
|
||||||
|
|
||||||
table_mutex.lock();
|
std::scoped_lock{table_mutex};
|
||||||
if (!generated) {
|
if (!generated) {
|
||||||
hashes = new std::array<Hash, HashCount>();
|
hashes = new std::array<Hash, HashCount>();
|
||||||
factors = new std::array<Vector4, OrderCount>();
|
factors = new std::array<Vector4, OrderCount>();
|
||||||
@ -85,8 +85,6 @@ template <size_t N> class OrderTable {
|
|||||||
|
|
||||||
generated = true;
|
generated = true;
|
||||||
}
|
}
|
||||||
table_mutex.unlock();
|
|
||||||
|
|
||||||
assert(generated);
|
assert(generated);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com> and licenced under the public domain
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com> and licenced under the public domain
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Quicktex Texture Compression Library
|
/* Quicktex Texture Compression Library
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||||
and licenced under the public domain
|
and licenced under the public domain
|
||||||
|
|
||||||
|
24
setup.py
24
setup.py
@ -1,9 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import pybind11
|
import sys
|
||||||
|
|
||||||
|
import pybind11
|
||||||
from setuptools import setup, Extension
|
from setuptools import setup, Extension
|
||||||
from setuptools.command.build_ext import build_ext
|
from setuptools.command.build_ext import build_ext
|
||||||
|
|
||||||
@ -31,7 +31,9 @@ class CMakeBuild(build_ext):
|
|||||||
if not extdir.endswith(os.path.sep):
|
if not extdir.endswith(os.path.sep):
|
||||||
extdir += os.path.sep
|
extdir += os.path.sep
|
||||||
|
|
||||||
cfg = "Debug" if self.debug else "Release"
|
cfg = "Debug" if self.debug else "RelWithDebInfo"
|
||||||
|
if 'QUICKTEX_DEBUG' in os.environ:
|
||||||
|
cfg = "Debug"
|
||||||
|
|
||||||
# CMake lets you override the generator - we need to check this.
|
# CMake lets you override the generator - we need to check this.
|
||||||
# Can be set with Conda-Build, for example.
|
# Can be set with Conda-Build, for example.
|
||||||
@ -43,7 +45,8 @@ class CMakeBuild(build_ext):
|
|||||||
"-Dpybind11_DIR={}".format(pybind11.get_cmake_dir()),
|
"-Dpybind11_DIR={}".format(pybind11.get_cmake_dir()),
|
||||||
"-DPython_EXECUTABLE={}".format(sys.executable),
|
"-DPython_EXECUTABLE={}".format(sys.executable),
|
||||||
"-DPython_ROOT_DIR={}".format(os.path.dirname(sys.executable)),
|
"-DPython_ROOT_DIR={}".format(os.path.dirname(sys.executable)),
|
||||||
"-DQUICKTEX_VERSION_INFO={}".format(version),
|
"-DQUICKTEX_VERSION_INFO={}".format(version), # include version info in module
|
||||||
|
"-DQUICKTEX_MODULE_ONLY=TRUE", # only build the module, not the wrapper
|
||||||
"-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm
|
"-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm
|
||||||
# clear cached make program binary, see https://github.com/pypa/setuptools/issues/2912
|
# clear cached make program binary, see https://github.com/pypa/setuptools/issues/2912
|
||||||
"-U",
|
"-U",
|
||||||
@ -68,12 +71,7 @@ class CMakeBuild(build_ext):
|
|||||||
contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"})
|
contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"})
|
||||||
|
|
||||||
# Convert distutils Windows platform specifiers to CMake -A arguments
|
# Convert distutils Windows platform specifiers to CMake -A arguments
|
||||||
plat_to_cmake = {
|
plat_to_cmake = {"win32": "Win32", "win-amd64": "x64", "win-arm32": "ARM", "win-arm64": "ARM64"}
|
||||||
"win32": "Win32",
|
|
||||||
"win-amd64": "x64",
|
|
||||||
"win-arm32": "ARM",
|
|
||||||
"win-arm64": "ARM64",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Specify the arch if using MSVC generator, but only if it doesn't
|
# Specify the arch if using MSVC generator, but only if it doesn't
|
||||||
# contain a backward-compatibility arch spec already in the
|
# contain a backward-compatibility arch spec already in the
|
||||||
@ -110,8 +108,4 @@ class CMakeBuild(build_ext):
|
|||||||
|
|
||||||
# The information here can also be placed in setup.cfg - better separation of
|
# The information here can also be placed in setup.cfg - better separation of
|
||||||
# logic and declaration, and simpler if you include description/version in a file.
|
# logic and declaration, and simpler if you include description/version in a file.
|
||||||
setup(
|
setup(use_scm_version=True, ext_modules=[CMakeExtension("_quicktex")], cmdclass={"build_ext": CMakeBuild})
|
||||||
use_scm_version=True,
|
|
||||||
ext_modules=[CMakeExtension("_quicktex")],
|
|
||||||
cmdclass={"build_ext": CMakeBuild},
|
|
||||||
)
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/* Quicktex Texture Compression Library
|
|
||||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
|
||||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
|
||||||
and licenced under the public domain
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file allows for easy debugging in CLion or other IDEs that dont natively support cross-debugging between Python and C++
|
|
||||||
|
|
||||||
#include <pybind11/embed.h>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
|
||||||
using namespace pybind11::literals;
|
|
||||||
|
|
||||||
#define STRINGIFY(x) #x
|
|
||||||
#define MACRO_STRINGIFY(x) STRINGIFY(x)
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
py::scoped_interpreter guard{};
|
|
||||||
|
|
||||||
py::module_ site = py::module_::import("site");
|
|
||||||
|
|
||||||
site.attr("addsitedir")(CUSTOM_SYS_PATH);
|
|
||||||
|
|
||||||
py::module_ nose = py::module_::import("nose");
|
|
||||||
py::module_ tests = py::module_::import("tests");
|
|
||||||
py::list argv(1);
|
|
||||||
nose.attr("runmodule")("name"_a = "tests.test_bc1", "exit"_a = false);
|
|
||||||
}
|
|
@ -1,208 +1,206 @@
|
|||||||
import unittest
|
import math
|
||||||
from parameterized import parameterized, parameterized_class
|
|
||||||
from quicktex.s3tc.bc1 import BC1Block, BC1Texture, BC1Encoder, BC1Decoder
|
import pytest
|
||||||
from .images import BC1Blocks
|
|
||||||
from PIL import Image, ImageChops
|
from PIL import Image, ImageChops
|
||||||
|
|
||||||
in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same
|
from quicktex.s3tc.bc1 import BC1Block, BC1Texture, BC1Encoder, BC1Decoder
|
||||||
|
from .images import BC1Blocks
|
||||||
|
|
||||||
|
in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same in 5:6:5
|
||||||
out_endpoints = ((255, 255, 255, 255), (66, 69, 66, 255))
|
out_endpoints = ((255, 255, 255, 255), (66, 69, 66, 255))
|
||||||
selectors = [[0, 2, 3, 1]] * 4
|
selectors = [[0, 2, 3, 1]] * 4
|
||||||
block_bytes = b'\xff\xff\x28\x42\x78\x78\x78\x78'
|
block_bytes = b'\xff\xff\x28\x42\x78\x78\x78\x78'
|
||||||
|
|
||||||
|
|
||||||
class TestBC1Block(unittest.TestCase):
|
class TestBC1Block:
|
||||||
"""Tests for the BC1Block class"""
|
"""Tests for the BC1Block class"""
|
||||||
|
|
||||||
def test_size(self):
|
def test_size(self):
|
||||||
"""Test the size and dimensions of BC1Block"""
|
"""Test the size and dimensions of BC1Block"""
|
||||||
self.assertEqual(BC1Block.nbytes, 8, 'incorrect block size')
|
assert BC1Block.nbytes == 8
|
||||||
self.assertEqual(BC1Block.width, 4, 'incorrect block width')
|
assert BC1Block.width == 4
|
||||||
self.assertEqual(BC1Block.height, 4, 'incorrect block width')
|
assert BC1Block.height == 4
|
||||||
self.assertEqual(BC1Block.size, (4, 4), 'incorrect block dimensions')
|
assert BC1Block.size == (4, 4)
|
||||||
|
|
||||||
def test_buffer(self):
|
def test_buffer(self):
|
||||||
"""Test the buffer protocol of BC1Block"""
|
"""Test the buffer protocol of BC1Block"""
|
||||||
block = BC1Block()
|
block = BC1Block()
|
||||||
mv = memoryview(block)
|
mv = memoryview(block)
|
||||||
|
|
||||||
self.assertFalse(mv.readonly, 'buffer is readonly')
|
|
||||||
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
|
|
||||||
self.assertEqual(mv.ndim, 1, 'buffer is multidimensional')
|
|
||||||
self.assertEqual(mv.nbytes, BC1Block.nbytes, 'buffer is the wrong size')
|
|
||||||
self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
|
|
||||||
|
|
||||||
mv[:] = block_bytes
|
mv[:] = block_bytes
|
||||||
self.assertEqual(mv.tobytes(), block_bytes, 'incorrect buffer data')
|
|
||||||
|
assert not mv.readonly
|
||||||
|
assert mv.c_contiguous
|
||||||
|
assert mv.ndim == 1
|
||||||
|
assert mv.nbytes == 8
|
||||||
|
assert mv.format == 'B'
|
||||||
|
assert mv.tobytes() == block_bytes
|
||||||
|
assert mv.tobytes() == block.tobytes()
|
||||||
|
|
||||||
def test_constructor(self):
|
def test_constructor(self):
|
||||||
"""Test constructing a block out of endpoints and selectors"""
|
"""Test constructing a block out of endpoints and selectors"""
|
||||||
block = BC1Block(*in_endpoints, selectors)
|
block = BC1Block(*in_endpoints, selectors)
|
||||||
self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes')
|
assert block.tobytes() == block_bytes
|
||||||
self.assertEqual(block.selectors, selectors, 'incorrect selectors')
|
assert block.selectors == selectors
|
||||||
self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints')
|
assert block.endpoints == out_endpoints
|
||||||
self.assertFalse(block.is_3color, 'incorrect color mode')
|
assert not block.is_3color
|
||||||
|
|
||||||
def test_frombytes(self):
|
def test_frombytes(self):
|
||||||
"""Test constructing a block out of raw data"""
|
"""Test constructing a block out of raw data"""
|
||||||
block = BC1Block.frombytes(block_bytes)
|
block = BC1Block.frombytes(block_bytes)
|
||||||
self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes')
|
assert block.tobytes() == block_bytes
|
||||||
self.assertEqual(block.selectors, selectors, 'incorrect selectors')
|
assert block.selectors == selectors
|
||||||
self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints')
|
assert block.endpoints == out_endpoints
|
||||||
self.assertFalse(block.is_3color, 'incorrect color mode')
|
assert not block.is_3color
|
||||||
|
|
||||||
def test_eq(self):
|
def test_eq(self):
|
||||||
"""Test equality between two identical blocks"""
|
"""Test equality between two identical blocks"""
|
||||||
block1 = BC1Block.frombytes(block_bytes)
|
block1 = BC1Block.frombytes(block_bytes)
|
||||||
block2 = BC1Block.frombytes(block_bytes)
|
block2 = BC1Block.frombytes(block_bytes)
|
||||||
self.assertEqual(block1, block2, 'identical blocks not equal')
|
assert block1 == block2
|
||||||
|
|
||||||
|
|
||||||
@parameterized_class(
|
# noinspection PyMethodMayBeStatic
|
||||||
("name", "w", "h", "wb", "hb"), [("8x8", 8, 8, 2, 2), ("9x9", 9, 9, 3, 3), ("7x7", 7, 7, 2, 2), ("7x9", 7, 9, 2, 3)]
|
@pytest.mark.parametrize('w', [7, 8, 9])
|
||||||
)
|
@pytest.mark.parametrize('h', [7, 8, 9])
|
||||||
class TestBC1Texture(unittest.TestCase):
|
class TestBC1Texture:
|
||||||
def setUp(self):
|
def test_dimensions(self, w, h):
|
||||||
self.tex = BC1Texture(self.w, self.h)
|
"""Test dimensions of BC1Texture in pixels, blocks, and bytes"""
|
||||||
self.nbytes = self.wb * self.hb * BC1Block.nbytes
|
tex = BC1Texture(w, h)
|
||||||
|
wb = math.ceil(w / 4)
|
||||||
|
hb = math.ceil(h / 4)
|
||||||
|
|
||||||
def test_size(self):
|
assert tex.nbytes == BC1Block.nbytes * wb * hb # block width x block height
|
||||||
"""Test size of BC1Texture in bytes"""
|
assert len(tex.tobytes()) == tex.nbytes
|
||||||
self.assertEqual(self.tex.nbytes, self.nbytes, 'incorrect texture size')
|
|
||||||
self.assertEqual(len(self.tex.tobytes()), self.nbytes, 'incorrect texture size from tobytes')
|
|
||||||
|
|
||||||
def test_dimensions(self):
|
assert tex.width == w
|
||||||
"""Test dimensions of BC1Texture in pixels"""
|
assert tex.height == h
|
||||||
self.assertEqual(self.tex.width, self.w, 'incorrect texture width')
|
assert tex.size == (w, h)
|
||||||
self.assertEqual(self.tex.height, self.h, 'incorrect texture height')
|
|
||||||
self.assertEqual(self.tex.size, (self.w, self.h), 'incorrect texture dimensions')
|
|
||||||
|
|
||||||
def test_dimensions_blocks(self):
|
assert tex.width_blocks == wb
|
||||||
"""Test dimensions of BC1Texture in blocks"""
|
assert tex.height_blocks == hb
|
||||||
self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks')
|
assert tex.size_blocks == (wb, hb)
|
||||||
self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks')
|
|
||||||
self.assertEqual(self.tex.size_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks')
|
|
||||||
|
|
||||||
def test_blocks(self):
|
def test_blocks(self, w, h):
|
||||||
"""Test getting and setting blocks to BC1Texture"""
|
"""Test getting and setting blocks to BC1Texture"""
|
||||||
blocks = [[BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)]
|
tex = BC1Texture(w, h)
|
||||||
for x in range(self.wb):
|
|
||||||
for y in range(self.hb):
|
|
||||||
self.tex[x, y] = blocks[y][x]
|
|
||||||
|
|
||||||
b = self.tex.tobytes()
|
# generate garbage blocks with the x and y index in the first 2 bytes
|
||||||
for x in range(self.wb):
|
blocks = [
|
||||||
for y in range(self.hb):
|
[BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(tex.width_blocks)]
|
||||||
index = (x + (y * self.wb)) * BC1Block.nbytes
|
for y in range(tex.height_blocks)
|
||||||
tb = self.tex[x, y]
|
]
|
||||||
|
# assign those blocks to the texture
|
||||||
|
for x in range(tex.width_blocks):
|
||||||
|
for y in range(tex.height_blocks):
|
||||||
|
tex[x, y] = blocks[y][x]
|
||||||
|
|
||||||
|
# get the blocks and analyze
|
||||||
|
b = tex.tobytes()
|
||||||
|
for x in range(tex.width_blocks):
|
||||||
|
for y in range(tex.height_blocks):
|
||||||
|
index = (x + (y * tex.width_blocks)) * BC1Block.nbytes
|
||||||
|
tb = tex[x, y]
|
||||||
fb = BC1Block.frombytes(b[index : index + BC1Block.nbytes])
|
fb = BC1Block.frombytes(b[index : index + BC1Block.nbytes])
|
||||||
self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture')
|
assert tb == blocks[y][x]
|
||||||
self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes')
|
assert fb == blocks[y][x]
|
||||||
|
|
||||||
self.assertEqual(self.tex[-1, -1], self.tex[self.wb - 1, self.hb - 1], 'incorrect negative subscripting')
|
def text_subscript(self, w, h):
|
||||||
|
"""Test BC1Texture subscripting for blocks"""
|
||||||
|
tex = BC1Texture(w, h)
|
||||||
|
|
||||||
with self.assertRaises(IndexError):
|
# ensure negative wraparound works
|
||||||
_ = self.tex[self.wb, self.hb]
|
assert tex[-1, -1] == tex[tex.width_blocks - 1, tex.height_blocks - 1]
|
||||||
with self.assertRaises(IndexError):
|
|
||||||
_ = self.tex[-1 - self.wb, -1 - self.hb]
|
|
||||||
|
|
||||||
def test_buffer(self):
|
with pytest.raises(IndexError):
|
||||||
|
_ = tex[tex.width_blocks, tex.height_blocks]
|
||||||
|
with pytest.raises(IndexError):
|
||||||
|
_ = tex[-1 - tex.width_blocks, -1 - tex.height_blocks]
|
||||||
|
|
||||||
|
def test_buffer(self, w, h):
|
||||||
"""Test the buffer protocol of BC1Texture"""
|
"""Test the buffer protocol of BC1Texture"""
|
||||||
mv = memoryview(self.tex)
|
tex = BC1Texture(w, h)
|
||||||
|
mv = memoryview(tex)
|
||||||
|
|
||||||
self.assertFalse(mv.readonly, 'buffer is readonly')
|
data = block_bytes * tex.width_blocks * tex.height_blocks
|
||||||
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
|
|
||||||
self.assertEqual(mv.nbytes, self.nbytes, 'buffer is the wrong size')
|
|
||||||
self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
|
|
||||||
|
|
||||||
data = block_bytes * self.wb * self.hb
|
|
||||||
mv[:] = data
|
mv[:] = data
|
||||||
self.assertEqual(mv.tobytes(), data, 'incorrect buffer data')
|
|
||||||
|
assert not mv.readonly
|
||||||
|
assert mv.c_contiguous
|
||||||
|
assert mv.nbytes == tex.nbytes
|
||||||
|
assert mv.format == 'B'
|
||||||
|
assert mv.tobytes() == data
|
||||||
|
|
||||||
|
|
||||||
@parameterized_class(
|
@pytest.mark.parametrize(
|
||||||
("name", "color_mode"),
|
'color_mode',
|
||||||
[
|
[BC1Encoder.ColorMode.FourColor, BC1Encoder.ColorMode.ThreeColor, BC1Encoder.ColorMode.ThreeColorBlack],
|
||||||
("4Color", BC1Encoder.ColorMode.FourColor),
|
|
||||||
("3Color", BC1Encoder.ColorMode.ThreeColor),
|
|
||||||
("3Color_Black", BC1Encoder.ColorMode.ThreeColorBlack),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
class TestBC1Encoder(unittest.TestCase):
|
class TestBC1Encoder:
|
||||||
"""Test BC1Encoder"""
|
"""Test BC1Encoder"""
|
||||||
|
|
||||||
@classmethod
|
def test_block_4color(self, color_mode):
|
||||||
def setUpClass(cls):
|
|
||||||
cls.bc1_encoder = BC1Encoder(5, cls.color_mode)
|
|
||||||
|
|
||||||
def test_block_4color(self):
|
|
||||||
"""Test encoder output with 4 color greyscale test block"""
|
"""Test encoder output with 4 color greyscale test block"""
|
||||||
out_tex = self.bc1_encoder.encode(BC1Blocks.greyscale.texture)
|
encoder = BC1Encoder(color_mode=color_mode)
|
||||||
|
out_tex = encoder.encode(BC1Blocks.greyscale.texture)
|
||||||
self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks')
|
|
||||||
|
|
||||||
out_block = out_tex[0, 0]
|
out_block = out_tex[0, 0]
|
||||||
|
|
||||||
self.assertFalse(out_block.is_3color, 'returned 3color mode for greyscale test block')
|
assert out_tex.size_blocks == (1, 1)
|
||||||
self.assertEqual(out_block, BC1Blocks.greyscale.block, 'encoded block is incorrect')
|
|
||||||
|
|
||||||
def test_block_3color(self):
|
assert not out_block.is_3color
|
||||||
|
assert out_block == BC1Blocks.greyscale.block
|
||||||
|
|
||||||
|
def test_block_3color(self, color_mode):
|
||||||
"""Test encoder output with 3 color test block"""
|
"""Test encoder output with 3 color test block"""
|
||||||
out_tex = self.bc1_encoder.encode(BC1Blocks.three_color.texture)
|
encoder = BC1Encoder(color_mode=color_mode)
|
||||||
|
out_tex = encoder.encode(BC1Blocks.three_color.texture)
|
||||||
self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks')
|
|
||||||
|
|
||||||
out_block = out_tex[0, 0]
|
out_block = out_tex[0, 0]
|
||||||
|
|
||||||
if self.color_mode != BC1Encoder.ColorMode.FourColor:
|
assert out_tex.size_blocks == (1, 1)
|
||||||
|
|
||||||
|
if encoder.color_mode != BC1Encoder.ColorMode.FourColor:
|
||||||
# we only care about the selectors if we are in 3 color mode
|
# we only care about the selectors if we are in 3 color mode
|
||||||
self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block')
|
assert out_block.is_3color
|
||||||
self.assertEqual(out_block, BC1Blocks.three_color.block, 'encoded block is incorrect')
|
assert out_block == BC1Blocks.three_color.block
|
||||||
else:
|
else:
|
||||||
self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode')
|
assert not out_block.is_3color
|
||||||
|
|
||||||
def test_block_3color_black(self):
|
def test_block_3color_black(self, color_mode):
|
||||||
"""Test encoder output with 3 color test block with black pixels"""
|
"""Test encoder output with 3 color test block with black pixels"""
|
||||||
out_tex = self.bc1_encoder.encode(BC1Blocks.three_color_black.texture)
|
encoder = BC1Encoder(color_mode=color_mode)
|
||||||
|
out_tex = encoder.encode(BC1Blocks.three_color_black.texture)
|
||||||
self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks')
|
|
||||||
|
|
||||||
out_block = out_tex[0, 0]
|
out_block = out_tex[0, 0]
|
||||||
|
|
||||||
|
assert out_tex.size_blocks == (1, 1)
|
||||||
|
|
||||||
has_black = 3 in [j for row in out_block.selectors for j in row]
|
has_black = 3 in [j for row in out_block.selectors for j in row]
|
||||||
|
|
||||||
if self.color_mode == BC1Encoder.ColorMode.ThreeColorBlack:
|
if color_mode == BC1Encoder.ColorMode.ThreeColorBlack:
|
||||||
# we only care about the selectors if we are in 3 color black mode
|
# we only care about the selectors if we are in 3 color black mode
|
||||||
self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block with black')
|
assert out_block.is_3color
|
||||||
self.assertTrue(has_black, 'block does not have black pixels as expected')
|
assert has_black
|
||||||
self.assertEqual(out_block, BC1Blocks.three_color_black.block, "encoded block is incorrect")
|
assert out_block == BC1Blocks.three_color_black.block
|
||||||
elif self.color_mode == BC1Encoder.ColorMode.ThreeColor:
|
elif color_mode == BC1Encoder.ColorMode.ThreeColor:
|
||||||
self.assertFalse(has_black and out_block.is_3color, 'returned 3color block with black pixels')
|
assert not (has_black and out_block.is_3color)
|
||||||
else:
|
else:
|
||||||
self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode')
|
assert not out_block.is_3color
|
||||||
|
|
||||||
|
|
||||||
class TestBC1Decoder(unittest.TestCase):
|
@pytest.mark.parametrize('texture', [BC1Blocks.greyscale, BC1Blocks.three_color, BC1Blocks.three_color_black])
|
||||||
|
class TestBC1Decoder:
|
||||||
"""Test BC1Decoder"""
|
"""Test BC1Decoder"""
|
||||||
|
|
||||||
@classmethod
|
def test_block(self, texture):
|
||||||
def setUpClass(cls):
|
|
||||||
cls.bc1_decoder = BC1Decoder()
|
|
||||||
|
|
||||||
@parameterized.expand(
|
|
||||||
[
|
|
||||||
("4color", BC1Blocks.greyscale.block, BC1Blocks.greyscale.image),
|
|
||||||
("3color", BC1Blocks.three_color.block, BC1Blocks.three_color.image),
|
|
||||||
("3color_black", BC1Blocks.three_color_black.block, BC1Blocks.three_color_black.image),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def test_block(self, _, block, image):
|
|
||||||
"""Test decoder output for a single block"""
|
"""Test decoder output for a single block"""
|
||||||
|
block = texture.block
|
||||||
|
image = texture.image
|
||||||
|
decoder = BC1Decoder()
|
||||||
in_tex = BC1Texture(4, 4)
|
in_tex = BC1Texture(4, 4)
|
||||||
in_tex[0, 0] = block
|
in_tex[0, 0] = block
|
||||||
out_tex = self.bc1_decoder.decode(in_tex)
|
out_tex = decoder.decode(in_tex)
|
||||||
|
|
||||||
self.assertEqual(out_tex.size, (4, 4), 'decoded texture has incorrect dimensions')
|
assert out_tex.size == (4, 4)
|
||||||
|
|
||||||
out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes())
|
out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes())
|
||||||
img_diff = ImageChops.difference(out_img, image).convert('L')
|
img_diff = ImageChops.difference(out_img, image).convert('L')
|
||||||
img_hist = img_diff.histogram()
|
img_hist = img_diff.histogram()
|
||||||
self.assertEqual(16, img_hist[0], 'decoded block is incorrect')
|
assert img_hist[0] == 16
|
||||||
|
@ -1,178 +1,179 @@
|
|||||||
import unittest
|
import math
|
||||||
from parameterized import parameterized, parameterized_class
|
|
||||||
from quicktex.s3tc.bc4 import BC4Block, BC4Texture, BC4Encoder, BC4Decoder
|
import pytest
|
||||||
from .images import BC4Blocks
|
|
||||||
from PIL import Image, ImageChops
|
from PIL import Image, ImageChops
|
||||||
|
|
||||||
|
from quicktex.s3tc.bc4 import BC4Block, BC4Texture, BC4Encoder, BC4Decoder
|
||||||
|
from .images import BC4Blocks
|
||||||
|
|
||||||
class TestBC4Block(unittest.TestCase):
|
block_bytes = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA'
|
||||||
|
selectors = [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2
|
||||||
|
endpoints = (240, 16)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBC4Block:
|
||||||
"""Tests for the BC1Block class"""
|
"""Tests for the BC1Block class"""
|
||||||
|
|
||||||
block_bytes = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA'
|
|
||||||
selectors = [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2
|
|
||||||
endpoints = (240, 16)
|
|
||||||
|
|
||||||
def test_size(self):
|
def test_size(self):
|
||||||
"""Test the size and dimensions of BC4Block"""
|
"""Test the size and dimensions of BC4Block"""
|
||||||
self.assertEqual(BC4Block.nbytes, 8, 'incorrect block size')
|
assert BC4Block.nbytes == 8
|
||||||
self.assertEqual(BC4Block.width, 4, 'incorrect block width')
|
assert BC4Block.width == 4
|
||||||
self.assertEqual(BC4Block.height, 4, 'incorrect block width')
|
assert BC4Block.height == 4
|
||||||
self.assertEqual(BC4Block.size, (4, 4), 'incorrect block dimensions')
|
assert BC4Block.size == (4, 4)
|
||||||
|
|
||||||
def test_buffer(self):
|
def test_buffer(self):
|
||||||
"""Test the buffer protocol of BC4Block"""
|
"""Test the buffer protocol of BC4Block"""
|
||||||
block = BC4Block()
|
block = BC4Block()
|
||||||
mv = memoryview(block)
|
mv = memoryview(block)
|
||||||
|
mv[:] = block_bytes
|
||||||
|
|
||||||
self.assertFalse(mv.readonly, 'buffer is readonly')
|
assert not mv.readonly
|
||||||
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
|
assert mv.c_contiguous
|
||||||
self.assertEqual(mv.ndim, 1, 'buffer is multidimensional')
|
assert mv.ndim == 1
|
||||||
self.assertEqual(mv.nbytes, BC4Block.nbytes, 'buffer is the wrong size')
|
assert mv.nbytes == 8
|
||||||
self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
|
assert mv.format == 'B'
|
||||||
|
assert mv.tobytes() == block_bytes
|
||||||
mv[:] = self.block_bytes
|
assert mv.tobytes() == block.tobytes()
|
||||||
self.assertEqual(mv.tobytes(), self.block_bytes, 'incorrect buffer data')
|
|
||||||
|
|
||||||
def test_constructor(self):
|
def test_constructor(self):
|
||||||
"""Test constructing a block out of endpoints and selectors"""
|
"""Test constructing a block out of endpoints and selectors"""
|
||||||
block = BC4Block(*self.endpoints, self.selectors)
|
block = BC4Block(*endpoints, selectors)
|
||||||
self.assertEqual(block.tobytes(), self.block_bytes, 'incorrect block bytes')
|
assert block.tobytes() == block_bytes
|
||||||
self.assertEqual(block.selectors, self.selectors, 'incorrect selectors')
|
assert block.selectors == selectors
|
||||||
self.assertEqual(block.endpoints, self.endpoints, 'incorrect endpoints')
|
assert block.endpoints == endpoints
|
||||||
|
|
||||||
def test_frombytes(self):
|
def test_frombytes(self):
|
||||||
"""Test constructing a block out of raw data"""
|
"""Test constructing a block out of raw data"""
|
||||||
block = BC4Block.frombytes(self.block_bytes)
|
block = BC4Block.frombytes(block_bytes)
|
||||||
self.assertEqual(block.tobytes(), self.block_bytes, 'incorrect block bytes')
|
assert block.tobytes() == block_bytes
|
||||||
self.assertEqual(block.selectors, self.selectors, 'incorrect selectors')
|
assert block.selectors == selectors
|
||||||
self.assertEqual(block.endpoints, self.endpoints, 'incorrect endpoints')
|
assert block.endpoints == endpoints
|
||||||
|
|
||||||
def test_eq(self):
|
def test_eq(self):
|
||||||
"""Test equality between two identical blocks"""
|
"""Test equality between two identical blocks"""
|
||||||
block1 = BC4Block.frombytes(self.block_bytes)
|
block1 = BC4Block.frombytes(block_bytes)
|
||||||
block2 = BC4Block.frombytes(self.block_bytes)
|
block2 = BC4Block.frombytes(block_bytes)
|
||||||
self.assertEqual(block1, block2, 'identical blocks not equal')
|
assert block1 == block2
|
||||||
|
|
||||||
def test_values_6(self):
|
def test_values_6(self):
|
||||||
"""Test values of a 6-value block"""
|
"""Test values of a 6-value block"""
|
||||||
block = BC4Block(8, 248, [[0] * 4] * 4)
|
block = BC4Block(8, 248, [[0] * 4] * 4)
|
||||||
|
|
||||||
self.assertEqual(block.values, [8, 248, 56, 104, 152, 200, 0, 255], 'incorrect values')
|
assert block.values == [8, 248, 56, 104, 152, 200, 0, 255]
|
||||||
self.assertTrue(block.is_6value, 'incorrect is_6value')
|
assert block.is_6value
|
||||||
|
|
||||||
def test_values_8(self):
|
def test_values_8(self):
|
||||||
"""Test values of an 8-value block"""
|
"""Test values of an 8-value block"""
|
||||||
block = BC4Block(240, 16, [[0] * 4] * 4)
|
block = BC4Block(240, 16, [[0] * 4] * 4)
|
||||||
|
|
||||||
self.assertEqual(block.values, [240, 16, 208, 176, 144, 112, 80, 48], 'incorrect values')
|
assert block.values == [240, 16, 208, 176, 144, 112, 80, 48]
|
||||||
self.assertFalse(block.is_6value, 'incorrect is_6value')
|
assert not block.is_6value
|
||||||
|
|
||||||
|
|
||||||
@parameterized_class(
|
# noinspection PyMethodMayBeStatic
|
||||||
("name", "w", "h", "wb", "hb"), [("8x8", 8, 8, 2, 2), ("9x9", 9, 9, 3, 3), ("7x7", 7, 7, 2, 2), ("7x9", 7, 9, 2, 3)]
|
@pytest.mark.parametrize('w', [7, 8, 9])
|
||||||
)
|
@pytest.mark.parametrize('h', [7, 8, 9])
|
||||||
class TestBC4Texture(unittest.TestCase):
|
class TestBC4Texture:
|
||||||
def setUp(self):
|
def test_dimensions(self, w, h):
|
||||||
self.tex = BC4Texture(self.w, self.h)
|
"""Test dimensions of BC4Texture in pixels, blocks, and bytes"""
|
||||||
self.nbytes = self.wb * self.hb * BC4Block.nbytes
|
tex = BC4Texture(w, h)
|
||||||
|
wb = math.ceil(w / 4)
|
||||||
|
hb = math.ceil(h / 4)
|
||||||
|
|
||||||
def test_size(self):
|
assert tex.nbytes == BC4Block.nbytes * wb * hb # block width x block height
|
||||||
"""Test size of BC4Texture in bytes"""
|
assert len(tex.tobytes()) == tex.nbytes
|
||||||
self.assertEqual(self.tex.nbytes, self.nbytes, 'incorrect texture size')
|
|
||||||
self.assertEqual(len(self.tex.tobytes()), self.nbytes, 'incorrect texture size from tobytes')
|
|
||||||
|
|
||||||
def test_dimensions(self):
|
assert tex.width == w
|
||||||
"""Test dimensions of BC4Texture in pixels"""
|
assert tex.height == h
|
||||||
self.assertEqual(self.tex.width, self.w, 'incorrect texture width')
|
assert tex.size == (w, h)
|
||||||
self.assertEqual(self.tex.height, self.h, 'incorrect texture height')
|
|
||||||
self.assertEqual(self.tex.size, (self.w, self.h), 'incorrect texture dimensions')
|
|
||||||
|
|
||||||
def test_dimensions_blocks(self):
|
assert tex.width_blocks == wb
|
||||||
"""Test dimensions of BC4Texture in blocks"""
|
assert tex.height_blocks == hb
|
||||||
self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks')
|
assert tex.size_blocks == (wb, hb)
|
||||||
self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks')
|
|
||||||
self.assertEqual(self.tex.size_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks')
|
|
||||||
|
|
||||||
def test_blocks(self):
|
def test_blocks(self, w, h):
|
||||||
"""Test getting and setting blocks to BC4Texture"""
|
"""Test getting and setting blocks to BC4Texture"""
|
||||||
blocks = [[BC4Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)]
|
tex = BC4Texture(w, h)
|
||||||
for x in range(self.wb):
|
|
||||||
for y in range(self.hb):
|
|
||||||
self.tex[x, y] = blocks[y][x]
|
|
||||||
|
|
||||||
b = self.tex.tobytes()
|
# generate garbage blocks with the x and y index in the first 2 bytes
|
||||||
for x in range(self.wb):
|
blocks = [
|
||||||
for y in range(self.hb):
|
[BC4Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(tex.width_blocks)]
|
||||||
index = (x + (y * self.wb)) * BC4Block.nbytes
|
for y in range(tex.height_blocks)
|
||||||
tb = self.tex[x, y]
|
]
|
||||||
|
# assign those blocks to the texture
|
||||||
|
for x in range(tex.width_blocks):
|
||||||
|
for y in range(tex.height_blocks):
|
||||||
|
tex[x, y] = blocks[y][x]
|
||||||
|
|
||||||
|
# get the blocks and analyze
|
||||||
|
b = tex.tobytes()
|
||||||
|
for x in range(tex.width_blocks):
|
||||||
|
for y in range(tex.height_blocks):
|
||||||
|
index = (x + (y * tex.width_blocks)) * BC4Block.nbytes
|
||||||
|
tb = tex[x, y]
|
||||||
fb = BC4Block.frombytes(b[index : index + BC4Block.nbytes])
|
fb = BC4Block.frombytes(b[index : index + BC4Block.nbytes])
|
||||||
self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture')
|
assert tb == blocks[y][x]
|
||||||
self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes')
|
assert fb == blocks[y][x]
|
||||||
|
|
||||||
self.assertEqual(self.tex[-1, -1], self.tex[self.wb - 1, self.hb - 1], 'incorrect negative subscripting')
|
def text_subscript(self, w, h):
|
||||||
|
"""Test BC4Texture subscripting for blocks"""
|
||||||
|
tex = BC4Texture(w, h)
|
||||||
|
|
||||||
with self.assertRaises(IndexError):
|
# ensure negative wraparound works
|
||||||
_ = self.tex[self.wb, self.hb]
|
assert tex[-1, -1] == tex[tex.width_blocks - 1, tex.height_blocks - 1]
|
||||||
with self.assertRaises(IndexError):
|
|
||||||
_ = self.tex[-1 - self.wb, -1 - self.hb]
|
|
||||||
|
|
||||||
def test_buffer(self):
|
with pytest.raises(IndexError):
|
||||||
"""Test the buffer protocol of BC4Texture"""
|
_ = tex[tex.width_blocks, tex.height_blocks]
|
||||||
mv = memoryview(self.tex)
|
with pytest.raises(IndexError):
|
||||||
|
_ = tex[-1 - tex.width_blocks, -1 - tex.height_blocks]
|
||||||
|
|
||||||
self.assertFalse(mv.readonly, 'buffer is readonly')
|
def test_buffer(self, w, h):
|
||||||
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
|
"""Test the buffer protocol of BC1Texture"""
|
||||||
self.assertEqual(mv.nbytes, self.nbytes, 'buffer is the wrong size')
|
tex = BC4Texture(w, h)
|
||||||
self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
|
mv = memoryview(tex)
|
||||||
|
|
||||||
data = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA' * self.wb * self.hb
|
data = block_bytes * tex.width_blocks * tex.height_blocks
|
||||||
mv[:] = data
|
mv[:] = data
|
||||||
self.assertEqual(mv.tobytes(), data, 'incorrect buffer data')
|
|
||||||
|
assert not mv.readonly
|
||||||
|
assert mv.c_contiguous
|
||||||
|
assert mv.nbytes == tex.nbytes
|
||||||
|
assert mv.format == 'B'
|
||||||
|
assert mv.tobytes() == data
|
||||||
|
|
||||||
|
|
||||||
class TestBC4Encoder(unittest.TestCase):
|
class TestBC4Encoder:
|
||||||
"""Test BC4Encoder"""
|
"""Test BC4Encoder"""
|
||||||
|
|
||||||
# 6-value blocks are not yet supported by the encoder so we only run one test
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.bc4_encoder = BC4Encoder(0)
|
|
||||||
|
|
||||||
def test_block(self):
|
def test_block(self):
|
||||||
"""Test encoder output with 8 value test block"""
|
"""Test encoder output with 8 value test block"""
|
||||||
out_tex = self.bc4_encoder.encode(BC4Blocks.eight_value.texture)
|
encoder = BC4Encoder(0)
|
||||||
|
out_tex = encoder.encode(BC4Blocks.eight_value.texture)
|
||||||
self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks')
|
|
||||||
|
|
||||||
out_block = out_tex[0, 0]
|
out_block = out_tex[0, 0]
|
||||||
|
|
||||||
self.assertFalse(out_block.is_6value, 'returned 6value mode')
|
assert out_tex.size_blocks == (1, 1)
|
||||||
self.assertEqual(out_block, BC4Blocks.eight_value.block, 'encoded block is incorrect')
|
|
||||||
|
assert not out_block.is_6value
|
||||||
|
assert out_block == BC4Blocks.eight_value.block
|
||||||
|
|
||||||
|
|
||||||
class TestBC4Decoder(unittest.TestCase):
|
@pytest.mark.parametrize('texture', [BC4Blocks.eight_value, BC4Blocks.six_value])
|
||||||
|
class TestBC4Decoder:
|
||||||
"""Test BC4Decoder"""
|
"""Test BC4Decoder"""
|
||||||
|
|
||||||
@classmethod
|
def test_block(self, texture):
|
||||||
def setUpClass(cls):
|
|
||||||
cls.bc4_decoder = BC4Decoder(0)
|
|
||||||
|
|
||||||
@parameterized.expand(
|
|
||||||
[
|
|
||||||
("8value", BC4Blocks.eight_value.block, BC4Blocks.eight_value.image),
|
|
||||||
("6value", BC4Blocks.six_value.block, BC4Blocks.six_value.image),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def test_block(self, _, block, image):
|
|
||||||
"""Test decoder output for a single block"""
|
"""Test decoder output for a single block"""
|
||||||
|
block = texture.block
|
||||||
|
image = texture.image
|
||||||
|
decoder = BC4Decoder(0)
|
||||||
in_tex = BC4Texture(4, 4)
|
in_tex = BC4Texture(4, 4)
|
||||||
in_tex[0, 0] = block
|
in_tex[0, 0] = block
|
||||||
out_tex = self.bc4_decoder.decode(in_tex)
|
out_tex = decoder.decode(in_tex)
|
||||||
|
|
||||||
self.assertEqual(out_tex.size, (4, 4), 'decoded texture has incorrect dimensions')
|
assert out_tex.size == (4, 4)
|
||||||
|
|
||||||
out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes())
|
out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes())
|
||||||
img_diff = ImageChops.difference(out_img, image).convert('L')
|
img_diff = ImageChops.difference(out_img, image).convert('L')
|
||||||
img_hist = img_diff.histogram()
|
img_hist = img_diff.histogram()
|
||||||
|
|
||||||
self.assertEqual(16, img_hist[0], 'decoded block is incorrect')
|
assert img_hist[0] == 16
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
"""Test if everything is installed correctly"""
|
"""Test if everything is installed correctly"""
|
||||||
|
|
||||||
import unittest
|
|
||||||
import os.path
|
|
||||||
import quicktex
|
import quicktex
|
||||||
|
|
||||||
tests_path = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
|
|
||||||
|
class TestInstall:
|
||||||
class TestInstall(unittest.TestCase):
|
|
||||||
def test_version(self):
|
def test_version(self):
|
||||||
"""Test if the extension module version matches what setuptools returns"""
|
"""Test if the extension module version matches what setuptools returns"""
|
||||||
try:
|
try:
|
||||||
|
@ -1,58 +1,60 @@
|
|||||||
import unittest
|
|
||||||
import os.path
|
import os.path
|
||||||
from .images import image_path
|
|
||||||
from quicktex import RawTexture
|
import pytest
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from quicktex import RawTexture
|
||||||
|
from .images import image_path
|
||||||
|
|
||||||
class TestRawTexture(unittest.TestCase):
|
|
||||||
|
class TestRawTexture:
|
||||||
boilerplate = Image.open(os.path.join(image_path, 'Boilerplate.png'))
|
boilerplate = Image.open(os.path.join(image_path, 'Boilerplate.png'))
|
||||||
boilerplate_bytes = boilerplate.tobytes('raw', 'RGBX')
|
boilerplate_bytes = boilerplate.tobytes('raw', 'RGBX')
|
||||||
width, height = boilerplate.size
|
width, height = boilerplate.size
|
||||||
size = width * height * 4
|
nbytes = width * height * 4
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.tex = RawTexture(self.width, self.height)
|
|
||||||
|
|
||||||
def test_size(self):
|
def test_size(self):
|
||||||
"""Test byte size and image dimensions"""
|
"""Test byte size and image dimensions"""
|
||||||
self.assertEqual(self.tex.nbytes, self.size, "incorrect texture byte size")
|
tex = RawTexture(self.width, self.height)
|
||||||
self.assertEqual(self.tex.width, self.width, "incorrect texture width")
|
assert tex.nbytes == self.nbytes
|
||||||
self.assertEqual(self.tex.height, self.height, "incorrect texture height")
|
assert tex.width == self.width
|
||||||
self.assertEqual(self.tex.size, (self.width, self.height), "incorrect texture dimensions")
|
assert tex.height == self.height
|
||||||
|
assert tex.size == (self.width, self.height)
|
||||||
|
|
||||||
def test_pixels(self):
|
def test_pixels(self):
|
||||||
"""Test getting and setting pixel values"""
|
"""Test getting and setting pixel values"""
|
||||||
|
tex = RawTexture(self.width, self.height)
|
||||||
color1 = (69, 13, 12, 0) # totally random color
|
color1 = (69, 13, 12, 0) # totally random color
|
||||||
color2 = (19, 142, 93, 44)
|
color2 = (19, 142, 93, 44)
|
||||||
|
|
||||||
self.tex[0, 0] = color1
|
tex[0, 0] = color1
|
||||||
self.tex[-1, -1] = color2
|
tex[-1, -1] = color2
|
||||||
data = self.tex.tobytes()
|
data = tex.tobytes()
|
||||||
|
|
||||||
self.assertEqual(self.tex[0, 0], color1)
|
assert tex[0, 0] == color1
|
||||||
self.assertEqual(self.tex[-1, -1], color2)
|
assert tex[-1, -1] == color2
|
||||||
self.assertEqual(tuple(data[0:4]), color1)
|
assert tuple(data[0:4]) == color1
|
||||||
self.assertEqual(tuple(data[-4:]), color2)
|
assert tuple(data[-4:]) == color2
|
||||||
|
|
||||||
with self.assertRaises(IndexError):
|
with pytest.raises(IndexError):
|
||||||
thing = self.tex[self.width, self.height]
|
_ = tex[self.width, self.height]
|
||||||
with self.assertRaises(IndexError):
|
with pytest.raises(IndexError):
|
||||||
thing = self.tex[-1 - self.width, -1 - self.height]
|
_ = tex[-1 - self.width, -1 - self.height]
|
||||||
|
|
||||||
def test_buffer(self):
|
def test_buffer(self):
|
||||||
"""Test the Buffer protocol implementation for RawTexture"""
|
"""Test the Buffer protocol implementation for RawTexture"""
|
||||||
mv = memoryview(self.tex)
|
tex = RawTexture(self.width, self.height)
|
||||||
|
mv = memoryview(tex)
|
||||||
self.assertFalse(mv.readonly, 'buffer is readonly')
|
|
||||||
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
|
|
||||||
self.assertEqual(mv.nbytes, self.size, 'buffer is the wrong size')
|
|
||||||
self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
|
|
||||||
|
|
||||||
mv[:] = self.boilerplate_bytes
|
mv[:] = self.boilerplate_bytes
|
||||||
self.assertEqual(mv.tobytes(), self.boilerplate_bytes, 'incorrect buffer data')
|
|
||||||
|
assert not mv.readonly
|
||||||
|
assert mv.c_contiguous
|
||||||
|
assert mv.nbytes == self.nbytes
|
||||||
|
assert mv.format == 'B'
|
||||||
|
assert mv.tobytes() == self.boilerplate_bytes
|
||||||
|
assert mv.tobytes() == tex.tobytes()
|
||||||
|
|
||||||
def test_frombytes(self):
|
def test_frombytes(self):
|
||||||
"""Test the frombytes factory function"""
|
"""Test the frombytes factory function"""
|
||||||
bytetex = RawTexture.frombytes(self.boilerplate_bytes, *self.boilerplate.size)
|
bytetex = RawTexture.frombytes(self.boilerplate_bytes, *self.boilerplate.size)
|
||||||
self.assertEqual(self.boilerplate_bytes, bytetex.tobytes(), 'Incorrect bytes after writing to buffer')
|
assert self.boilerplate_bytes == bytetex.tobytes()
|
||||||
|
Loading…
Reference in New Issue
Block a user