OpenColorIO: upgrade to version 2.0.0

Ref T84819

Build System
============

This is an API breaking new version, and the updated code only builds with
OpenColorIO 2.0 and later. Adding backwards compatibility was too complicated.

* Tinyxml was replaced with Expat, adding a new dependency.
* Yaml-cpp is now built as a dependency on Unix, as was already done on Windows.
* Removed currently unused LCMS code.
* Pystring remains built as part of OCIO itself, since it has no good build system.
* Linux and macOS check for the OpenColorIO verison, and disable it if too old.

Ref D10270

Processors and Transforms
=========================

CPU processors now need to be created to do CPU processing. These are cached
internally, but the cache lookup is not fast enough to execute per pixel or
texture sample, so for performance these are now also exposed in the C API.

The C API for transforms will no longer be needed afer all changes, so remove
it to simplify the API and fallback implementation.

Ref D10271

Display Transforms
==================

Needs a bit more manual work constructing the transform. LegacyViewingPipeline
could also have been used, but isn't really any simpler and since it's legacy
we better not rely on it.

We moved more logic into the opencolorio module, to simplify the API. There is
no need to wrap a dozen functions just to be able to do this in C rather than C++.
It's also tightly coupled to the GPU shader logic, and so should be in the same
module.

Ref D10271

GPU Display Shader
==================

To avoid baking exposure and gamma into the GLSL shader and requiring slow
recompiles when tweaking, we manually apply them in the shader. This leads
to some logic duplicaton between the CPU and GPU display processor, but it
seems unavoidable.

Caching was also changed. Previously this was done both on the imbuf and
opencolorio module levels. Now it's all done in the opencolorio module by
simply matching color space names. We no longer use cacheIDs from OpenColorIO
since computing them is expensive, and they are unlikely to match now that
more is baked into the shader code.

Shaders can now use multiple 2D textures, 3D textures and uniforms, rather
than a single 3D texture. So allocating and binding those adds some code.

Color space conversions for blending with overlays is now hardcoded in the
shader. This was using harcoded numbers anyway, if this every becomes a
general OpenColorIO transform it can be changed, but for now there is no
point to add code complexity.

Ref D10273

CIE XYZ
=======

We need standard CIE XYZ values for rendering effects like blackbody emission.
The relation to the scene linear role is based on OpenColorIO configuration.

In OpenColorIO 2.0 configs roles can no longer have the same name as color
spaces, which means our XYZ role and colorspace in the configuration give an
error.

Instead use the new standard aces_interchange role, which relates scene linear
to a known scene referred color space. Compatibility with the old XYZ role is
preserved, if the configuration file has no conflicting names.

Also includes a non-functional change to the configuraton file to use an
XYZ-to-ACES matrix instead of REC709-to-ACES, makes debugging a little easier
since the matrix is the same one we have in the code now and that is also
found easily in the ACES specs.

Ref D10274
This commit is contained in:
Brecht Van Lommel 2021-01-31 19:35:00 +01:00
parent 6b40ee608c
commit 1b4961b318
Notes: blender-bot 2023-02-14 05:01:20 +01:00
Referenced by issue #85940, OpenColorIO 2.0 incompatible with Blender 2.91.2
Referenced by issue #85365, Libraries Changes for Blender 2.93
Referenced by issue #84819, OpenColorIO 2.0 Upgrade
30 changed files with 1358 additions and 1742 deletions

View File

@ -728,8 +728,9 @@ set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF)
# NanoVDB requires OpenVDB to convert the data structure
set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF)
# OpenVDB uses 'half' type from OpenEXR & fails to link without OpenEXR enabled.
# OpenVDB and OpenColorIO uses 'half' type from OpenEXR
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENCOLORIO OFF)
# Haru needs `TIFFFaxBlackCodes` & `TIFFFaxWhiteCodes` symbols from TIFF.
set_and_warn_dependency(WITH_IMAGE_TIFF WITH_HARU OFF)

View File

@ -70,7 +70,6 @@ include(cmake/cuew.cmake)
include(cmake/opensubdiv.cmake)
include(cmake/sdl.cmake)
include(cmake/opencollada.cmake)
include(cmake/opencolorio.cmake)
include(cmake/llvm.cmake)
include(cmake/clang.cmake)
if(APPLE)
@ -105,18 +104,15 @@ if(NOT APPLE)
include(cmake/xr_openxr.cmake)
endif()
# OpenColorIO and dependencies.
include(cmake/expat.cmake)
include(cmake/yamlcpp.cmake)
include(cmake/opencolorio.cmake)
if(WITH_WEBP)
include(cmake/webp.cmake)
endif()
if(WIN32)
# OCIO deps
include(cmake/tinyxml.cmake)
include(cmake/yamlcpp.cmake)
# LCMS is an OCIO dep, but only if you build the apps, leaving it here for convenience
# include(cmake/lcms.cmake)
endif()
if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/gmp.cmake)
include(cmake/openjpeg.cmake)

View File

@ -16,16 +16,20 @@
#
# ***** END GPL LICENSE BLOCK *****
set(LCMS_EXTRA_ARGS
set(EXPAT_EXTRA_ARGS
-DEXPAT_BUILD_DOCS=OFF
-DEXPAT_BUILD_EXAMPLES=OFF
-DEXPAT_BUILD_TESTS=OFF
-DEXPAT_BUILD_TOOLS=OFF
-DEXPAT_SHARED_LIBS=OFF
)
ExternalProject_Add(external_lcms
URL ${LCMS_URI}
ExternalProject_Add(external_expat
URL ${EXPAT_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${LCMS_HASH}
PREFIX ${BUILD_DIR}/lcms
# Patch taken from ocio.
PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_lcms.txt ${BUILD_DIR}/lcms/src/external_lcms/CMakeLists.txt
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/lcms ${DEFAULT_CMAKE_FLAGS} ${LCMS_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/lcms
URL_HASH MD5=${EXPAT_HASH}
PREFIX ${BUILD_DIR}/expat
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/expat ${DEFAULT_CMAKE_FLAGS} ${EXPAT_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/expat
SOURCE_SUBDIR expat
)

View File

@ -22,8 +22,8 @@ ExternalProject_Add(external_nasm
URL_HASH SHA256=${NASM_HASH}
PREFIX ${BUILD_DIR}/nasm
PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/nasm/src/external_nasm < ${PATCH_DIR}/nasm.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/nasm
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make -j${MAKE_THREADS}
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && ./autogen.sh && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/nasm
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make -j${MAKE_THREADS} && make manpages
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make install
INSTALL_DIR ${LIBDIR}/nasm
)

View File

@ -18,16 +18,22 @@
set(OPENCOLORIO_EXTRA_ARGS
-DOCIO_BUILD_APPS=OFF
-DOCIO_BUILD_PYGLUE=OFF
-DOCIO_BUILD_PYTHON=OFF
-DOCIO_BUILD_NUKE=OFF
-DOCIO_USE_BOOST_PTR=OFF
-DOCIO_BUILD_STATIC=ON
-DOCIO_BUILD_SHARED=OFF
-DOCIO_BUILD_TRUELIGHT=OFF
-DOCIO_BUILD_JAVA=OFF
-DBUILD_SHARED_LIBS=OFF
-DOCIO_BUILD_DOCS=OFF
-DOCIO_BUILD_PYGLUE=OFF
-DOCIO_BUILD_JNIGLUE=OFF
-DOCIO_STATIC_JNIGLUE=OFF
-DOCIO_BUILD_TESTS=OFF
-DOCIO_BUILD_GPU_TESTS=OFF
-DOCIO_USE_SSE=ON
# Manually build ext packages except for pystring, which does not have
# a CMake or autotools build system that we can easily use.
-DOCIO_INSTALL_EXT_PACKAGES=MISSING
-DHalf_ROOT=${LIBDIR}/openexr
-DHalf_STATIC_LIBRARY=ON
-Dexpat_ROOT=${LIBDIR}/expat
-Dyaml-cpp_ROOT=${LIBDIR}/yamlcpp
)
if(APPLE AND NOT("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64"))
@ -41,24 +47,7 @@ if(WIN32)
set(OCIO_PATCH opencolorio_win.diff)
set(OPENCOLORIO_EXTRA_ARGS
${OPENCOLORIO_EXTRA_ARGS}
-DOCIO_BUILD_TESTS=OFF
-DOCIO_USE_SSE=ON
-DOCIO_INLINES_HIDDEN=OFF
-DOCIO_PYGLUE_LINK=OFF
-DOCIO_PYGLUE_RESPECT_ABI=OFF
-DOCIO_PYGLUE_SONAME=OFF
-DOCIO_PYGLUE_LIB_PREFIX=OFF
-DUSE_EXTERNAL_TINYXML=ON
-DTINYXML_INCLUDE_DIR=${LIBDIR}/tinyxml/include
-DTINYXML_LIBRARY=${LIBDIR}/tinyxml/lib/tinyxml${libext}
-DUSE_EXTERNAL_YAML=ON
-DYAML_CPP_FOUND=ON
-DYAML_CPP_VERSION=${YAMLCPP_VERSION}
-DUSE_EXTERNAL_LCMS=ON
-DINC_1=${LIBDIR}/tinyxml/include
-DINC_2=${LIBDIR}/yamlcpp/include
# Lie because ocio cmake is demanding boost even though it is not needed.
-DYAML_CPP_VERSION=0.5.0
)
else()
set(OCIO_PATCH opencolorio.diff)
@ -72,48 +61,42 @@ ExternalProject_Add(external_opencolorio
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${OPENCOLORIO_HASH}
PREFIX ${BUILD_DIR}/opencolorio
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencolorio/src/external_opencolorio < ${PATCH_DIR}/${OCIO_PATCH}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencolorio ${DEFAULT_CMAKE_FLAGS} ${OPENCOLORIO_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/opencolorio
)
if(NOT WIN32)
add_custom_command(
OUTPUT ${LIBDIR}/opencolorio/lib/libtinyxml.a
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libtinyxml.a ${LIBDIR}/opencolorio/lib/libtinyxml.a
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/libyaml-cpp.a
)
add_custom_target(external_opencolorio_extra ALL DEPENDS external_opencolorio ${LIBDIR}/opencolorio/lib/libtinyxml.a)
endif()
add_dependencies(
external_opencolorio
external_boost
external_yamlcpp
external_expat
external_openexr
)
if(WIN32)
add_dependencies(
external_opencolorio
external_tinyxml
external_yamlcpp
)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/include ${HARVEST_TARGET}/opencolorio/include
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/lib/static ${HARVEST_TARGET}/opencolorio/lib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/lib ${HARVEST_TARGET}/opencolorio/lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tinyxml/lib/tinyxml.lib ${HARVEST_TARGET}/opencolorio/lib/tinyxml.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/expat/lib/libexpatMD.lib ${HARVEST_TARGET}/opencolorio/lib/libexpatMD.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/pystring.lib ${HARVEST_TARGET}/opencolorio/lib/pystring.lib
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencolorio/lib/static/Opencolorio.lib ${HARVEST_TARGET}/opencolorio/lib/OpencolorIO_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencolorio/lib/Opencolorio.lib ${HARVEST_TARGET}/opencolorio/lib/OpencolorIO_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmdd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tinyxml/lib/tinyxml.lib ${HARVEST_TARGET}/opencolorio/lib/tinyxml_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/expat/lib/libexpatdMD.lib ${HARVEST_TARGET}/opencolorio/lib/libexpatdMD.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/pystring.lib ${HARVEST_TARGET}/opencolorio/lib/pystring_d.lib
DEPENDEES install
)
endif()
else()
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND cp ${LIBDIR}/yamlcpp/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/expat/lib/libexpat.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libpystring.a ${LIBDIR}/opencolorio/lib/
DEPENDEES install
)
endif()

View File

@ -1,31 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
set(TINYXML_EXTRA_ARGS
)
ExternalProject_Add(external_tinyxml
URL ${TINYXML_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${TINYXML_HASH}
PREFIX ${BUILD_DIR}/tinyxml
# patch taken from ocio
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/tinyxml/src/external_tinyxml < ${PATCH_DIR}/tinyxml.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/tinyxml ${DEFAULT_CMAKE_FLAGS} ${TINYXML_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/tinyxml
)

View File

@ -109,9 +109,9 @@ set(OPENCOLLADA_VERSION v1.6.68)
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
set(OPENCOLLADA_HASH ee7dae874019fea7be11613d07567493)
set(OPENCOLORIO_VERSION 1.1.1)
set(OPENCOLORIO_VERSION 2.0.0)
set(OPENCOLORIO_URI https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz)
set(OPENCOLORIO_HASH 23d8b9ac81599305539a5a8674b94a3d)
set(OPENCOLORIO_HASH 1a2e3478b6cd9a1549f24e1b2205e3f0)
set(LLVM_VERSION 9.0.1)
set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
@ -257,9 +257,9 @@ set(YAMLCPP_VERSION 0.6.3)
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
set(LCMS_VERSION 2.9)
set(LCMS_URI https://nchc.dl.sourceforge.net/project/lcms/lcms/${LCMS_VERSION}/lcms2-${LCMS_VERSION}.tar.gz)
set(LCMS_HASH 8de1b7724f578d2995c8fdfa35c3ad0e)
set(EXPAT_VERSION 2_2_10)
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
set(EXPAT_HASH 7ca5f09959fcb9a57618368deb627b9f)
set(PUGIXML_VERSION 1.10)
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
@ -314,8 +314,8 @@ set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa/mesa-${MESA_VERSION}.tar.xz)
set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
set(NASM_VERSION 2.15.02)
set(NASM_URI https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.xz)
set(NASM_HASH f4fd1329b1713e1ccd34b2fc121c4bcd278c9f91cc4cb205ae8fcd2e4728dd14)
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
set(XR_OPENXR_SDK_VERSION 1.0.8)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)

View File

@ -17,13 +17,18 @@
# ***** END GPL LICENSE BLOCK *****
set(YAMLCPP_EXTRA_ARGS
-DBUILD_GMOCK=OFF
-DYAML_CPP_BUILD_TESTS=OFF
-DYAML_CPP_BUILD_TOOLS=OFF
-DYAML_CPP_BUILD_CONTRIB=OFF
-DYAML_MSVC_SHARED_RT=ON
)
if(WIN32)
set(YAMLCPP_EXTRA_ARGS
${YAMLCPP_EXTRA_ARGS}
-DBUILD_GMOCK=OFF
-DYAML_MSVC_SHARED_RT=ON)
endif()
ExternalProject_Add(external_yamlcpp
URL ${YAMLCPP_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -454,10 +454,10 @@ TBB_FORCE_BUILD=false
TBB_FORCE_REBUILD=false
TBB_SKIP=false
OCIO_VERSION="1.1.1"
OCIO_VERSION_SHORT="1.1"
OCIO_VERSION_MIN="1.0"
OCIO_VERSION_MAX="1.2"
OCIO_VERSION="2.0.0"
OCIO_VERSION_SHORT="2.0"
OCIO_VERSION_MIN="2.0"
OCIO_VERSION_MAX="3.0"
OCIO_FORCE_BUILD=false
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
@ -1787,8 +1787,8 @@ compile_OCIO() {
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D OCIO_BUILD_APPS=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_PYGLUE=OFF"
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_PYTHON=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_GPU_TESTS=OFF"
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"

View File

@ -26,7 +26,8 @@ ENDIF()
SET(_opencolorio_FIND_COMPONENTS
OpenColorIO
yaml-cpp
tinyxml
expat
pystring
)
SET(_opencolorio_SEARCH_DIRS
@ -60,12 +61,23 @@ FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS})
ENDIF()
ENDFOREACH()
IF(EXISTS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h")
# Search twice, because this symbol changed between OCIO 1.x and 2.x
FILE(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" _opencolorio_version
REGEX "^#define OCIO_VERSION_STR[ \t].*$")
IF(NOT _opencolorio_version)
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" _opencolorio_version
REGEX "^#define OCIO_VERSION[ \t].*$")
ENDIF()
STRING(REGEX MATCHALL "[0-9]+[.0-9]+" OPENCOLORIO_VERSION ${_opencolorio_version})
ENDIF()
# handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO DEFAULT_MSG
_opencolorio_LIBRARIES OPENCOLORIO_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO
REQUIRED_VARS _opencolorio_LIBRARIES OPENCOLORIO_INCLUDE_DIR
VERSION_VAR OPENCOLORIO_VERSION)
IF(OPENCOLORIO_FOUND)
SET(OPENCOLORIO_LIBRARIES ${_opencolorio_LIBRARIES})
@ -78,6 +90,7 @@ MARK_AS_ADVANCED(
OPENCOLORIO_OPENCOLORIO_LIBRARY
OPENCOLORIO_TINYXML_LIBRARY
OPENCOLORIO_YAML-CPP_LIBRARY
OPENCOLORIO_VERSION
)
UNSET(COMPONENT)

View File

@ -297,7 +297,12 @@ if(WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
find_package(OpenColorIO)
find_package(OpenColorIO 2.0.0)
if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF)
message(STATUS "OpenColorIO not found")
endif()
endif()
if(WITH_OPENVDB)

View File

@ -385,7 +385,7 @@ if(WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
find_package_wrapper(OpenColorIO)
find_package_wrapper(OpenColorIO 2.0.0)
set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES})
set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere

View File

@ -500,7 +500,7 @@ if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
set(OPENCOLORIO_DEFINITIONS "-DDOpenColorIO_SKIP_IMPORTS")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
add_definitions(-DOIIO_STATIC_DEFINE)
add_definitions(-DOIIO_NO_SSE=1)
@ -538,11 +538,13 @@ if(WITH_OPENCOLORIO)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
optimized ${OPENCOLORIO_LIBPATH}/tinyxml.lib
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
debug ${OPENCOLORIO_LIBPATH}/tinyxml_d.lib
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
)
set(OPENCOLORIO_DEFINITIONS)
endif()

View File

@ -133,8 +133,11 @@ if(WITH_OPENCOLORIO)
SYSTEM
${OPENCOLORIO_INCLUDE_DIRS}
)
list(APPEND LIB
${OPENCOLORIO_LIBRARIES}
)
if(WIN32)
add_definitions(-DOpenColorIO_STATIC)
add_definitions(-DOpenColorIO_SKIP_IMPORTS)
endif()
endif()

View File

@ -192,6 +192,7 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
return;
}
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
is_scene_linear = true;
is_srgb = true;
for (int i = 0; i < 256; i++) {
@ -201,10 +202,10 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
float cG[3] = {0, v, 0};
float cB[3] = {0, 0, v};
float cW[3] = {v, v, v};
processor->applyRGB(cR);
processor->applyRGB(cG);
processor->applyRGB(cB);
processor->applyRGB(cW);
device_processor->applyRGB(cR);
device_processor->applyRGB(cG);
device_processor->applyRGB(cB);
device_processor->applyRGB(cW);
/* Make sure that there is no channel crosstalk. */
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
@ -267,6 +268,7 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
/* TODO: implement faster version for when we know the conversion
* is a simple matrix transform between linear spaces. In that case
* un-premultiply is not needed. */
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
/* Process large images in chunks to keep temporary memory requirement down. */
const size_t chunk_size = std::min((size_t)(16 * 1024 * 1024), num_pixels);
@ -289,7 +291,7 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
}
OCIO::PackedImageDesc desc((float *)float_pixels.data(), width, 1, 4);
processor->apply(desc);
device_processor->apply(desc);
for (size_t i = 0; i < width; i++) {
float4 value = float_pixels[i];
@ -345,13 +347,14 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
const OCIO::Processor *processor = (const OCIO::Processor *)processor_;
if (processor) {
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
if (channels == 3) {
processor->applyRGB(pixel);
device_processor->applyRGB(pixel);
}
else if (channels == 4) {
if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
/* Fast path for RGBA. */
processor->applyRGB(pixel);
device_processor->applyRGB(pixel);
}
else {
/* Un-associate and associate alpha since color management should not
@ -363,7 +366,7 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha;
processor->applyRGB(pixel);
device_processor->applyRGB(pixel);
pixel[0] *= alpha;
pixel[1] *= alpha;

View File

@ -35,6 +35,7 @@
#include "util/util_foreach.h"
#include "util/util_murmurhash.h"
#include "util/util_task.h"
#include "util/util_transform.h"
#ifdef WITH_OCIO
# include <OpenColorIO/OpenColorIO.h>
@ -399,39 +400,7 @@ ShaderManager::ShaderManager()
update_flags = UPDATE_ALL;
beckmann_table_offset = TABLE_OFFSET_INVALID;
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
if (config) {
if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
if (to_rgb_processor && to_xyz_processor) {
float r[] = {1.0f, 0.0f, 0.0f};
float g[] = {0.0f, 1.0f, 0.0f};
float b[] = {0.0f, 0.0f, 1.0f};
to_xyz_processor->applyRGB(r);
to_xyz_processor->applyRGB(g);
to_xyz_processor->applyRGB(b);
rgb_to_y = make_float3(r[1], g[1], b[1]);
float x[] = {1.0f, 0.0f, 0.0f};
float y[] = {0.0f, 1.0f, 0.0f};
float z[] = {0.0f, 0.0f, 1.0f};
to_rgb_processor->applyRGB(x);
to_rgb_processor->applyRGB(y);
to_rgb_processor->applyRGB(z);
xyz_to_r = make_float3(x[0], y[0], z[0]);
xyz_to_g = make_float3(x[1], y[1], z[1]);
xyz_to_b = make_float3(x[2], y[2], z[2]);
}
}
}
#endif
init_xyz_transforms();
}
ShaderManager::~ShaderManager()
@ -829,4 +798,89 @@ bool ShaderManager::need_update() const
return update_flags != UPDATE_NONE;
}
#ifdef WITH_OCIO
static bool to_scene_linear_transform(OCIO::ConstConfigRcPtr &config,
const char *colorspace,
Transform &to_scene_linear)
{
OCIO::ConstProcessorRcPtr processor;
try {
processor = config->getProcessor(OCIO::ROLE_SCENE_LINEAR, colorspace);
}
catch (OCIO::Exception &exception) {
return false;
}
if (!processor) {
return false;
}
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
if (!device_processor) {
return false;
}
to_scene_linear = transform_identity();
device_processor->applyRGB(&to_scene_linear.x.x);
device_processor->applyRGB(&to_scene_linear.y.x);
device_processor->applyRGB(&to_scene_linear.z.x);
to_scene_linear = transform_transposed_inverse(to_scene_linear);
return true;
}
#endif
void ShaderManager::init_xyz_transforms()
{
/* Default to ITU-BT.709 in case no appropriate transform found. */
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
/* Get from OpenColorO config if it has the required roles. */
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
if (!(config && config->hasRole(OCIO::ROLE_SCENE_LINEAR))) {
return;
}
Transform xyz_to_rgb;
if (config->hasRole("aces_interchange")) {
/* Standard OpenColorIO role, defined as ACES2065-1. */
const Transform xyz_to_aces = make_transform(1.0498110175f,
0.0f,
-0.0000974845f,
0.0f,
-0.4959030231f,
1.3733130458f,
0.0982400361f,
0.0f,
0.0f,
0.0f,
0.9912520182f,
0.0f);
Transform aces_to_rgb;
if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
return;
}
xyz_to_rgb = aces_to_rgb * xyz_to_aces;
}
else if (config->hasRole("XYZ")) {
/* Custom role used before the standard existed. */
if (!to_scene_linear_transform(config, "XYZ", xyz_to_rgb)) {
return;
}
}
xyz_to_r = float4_to_float3(xyz_to_rgb.x);
xyz_to_g = float4_to_float3(xyz_to_rgb.y);
xyz_to_b = float4_to_float3(xyz_to_rgb.z);
const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
rgb_to_y = float4_to_float3(rgb_to_xyz.y);
#endif
}
CCL_NAMESPACE_END

View File

@ -221,6 +221,8 @@ class ShaderManager {
bool need_update() const;
void init_xyz_transforms();
protected:
ShaderManager();

View File

@ -34,7 +34,7 @@ using std::max;
enum TransformType {
TRANSFORM_LINEAR_TO_SRGB,
TRANSFORM_SRGB_TO_LINEAR,
TRANSFORM_MATRIX,
TRANSFORM_SCALE,
TRANSFORM_EXPONENT,
TRANSFORM_UNKNOWN,
};
@ -53,147 +53,72 @@ typedef struct OCIO_PackedImageDescription {
} OCIO_PackedImageDescription;
struct FallbackTransform {
FallbackTransform() : type(TRANSFORM_UNKNOWN), linear_transform(NULL), display_transform(NULL)
FallbackTransform() : type(TRANSFORM_UNKNOWN), scale(1.0f), exponent(1.0f)
{
}
virtual ~FallbackTransform()
{
delete linear_transform;
delete display_transform;
}
void applyRGB(float *pixel)
{
if (type == TRANSFORM_LINEAR_TO_SRGB) {
applyLinearRGB(pixel);
pixel[0] *= scale;
pixel[1] *= scale;
pixel[2] *= scale;
linearrgb_to_srgb_v3_v3(pixel, pixel);
applyDisplayRGB(pixel);
pixel[0] = powf(max(0.0f, pixel[0]), exponent);
pixel[1] = powf(max(0.0f, pixel[1]), exponent);
pixel[2] = powf(max(0.0f, pixel[2]), exponent);
}
else if (type == TRANSFORM_SRGB_TO_LINEAR) {
srgb_to_linearrgb_v3_v3(pixel, pixel);
}
else if (type == TRANSFORM_EXPONENT) {
pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]);
pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]);
pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]);
pixel[0] = powf(max(0.0f, pixel[0]), exponent);
pixel[1] = powf(max(0.0f, pixel[1]), exponent);
pixel[2] = powf(max(0.0f, pixel[2]), exponent);
}
else if (type == TRANSFORM_MATRIX) {
float r = pixel[0];
float g = pixel[1];
float b = pixel[2];
pixel[0] = r * matrix[0] + g * matrix[1] + b * matrix[2];
pixel[1] = r * matrix[4] + g * matrix[5] + b * matrix[6];
pixel[2] = r * matrix[8] + g * matrix[9] + b * matrix[10];
pixel[0] += offset[0];
pixel[1] += offset[1];
pixel[2] += offset[2];
else if (type == TRANSFORM_SCALE) {
pixel[0] *= scale;
pixel[1] *= scale;
pixel[2] *= scale;
}
}
void applyRGBA(float *pixel)
{
if (type == TRANSFORM_LINEAR_TO_SRGB) {
applyLinearRGBA(pixel);
linearrgb_to_srgb_v4(pixel, pixel);
applyDisplayRGBA(pixel);
}
else if (type == TRANSFORM_SRGB_TO_LINEAR) {
srgb_to_linearrgb_v4(pixel, pixel);
}
else if (type == TRANSFORM_EXPONENT) {
pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]);
pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]);
pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]);
pixel[3] = powf(max(0.0f, pixel[3]), exponent[3]);
}
else if (type == TRANSFORM_MATRIX) {
float r = pixel[0];
float g = pixel[1];
float b = pixel[2];
float a = pixel[3];
pixel[0] = r * matrix[0] + g * matrix[1] + b * matrix[2] + a * matrix[3];
pixel[1] = r * matrix[4] + g * matrix[5] + b * matrix[6] + a * matrix[7];
pixel[2] = r * matrix[8] + g * matrix[9] + b * matrix[10] + a * matrix[11];
pixel[3] = r * matrix[12] + g * matrix[13] + b * matrix[14] + a * matrix[15];
pixel[0] += offset[0];
pixel[1] += offset[1];
pixel[2] += offset[2];
pixel[3] += offset[3];
}
}
void applyLinearRGB(float *pixel)
{
if (linear_transform != NULL) {
linear_transform->applyRGB(pixel);
}
}
void applyLinearRGBA(float *pixel)
{
if (linear_transform != NULL) {
linear_transform->applyRGBA(pixel);
}
}
void applyDisplayRGB(float *pixel)
{
if (display_transform != NULL) {
display_transform->applyRGB(pixel);
}
}
void applyDisplayRGBA(float *pixel)
{
if (display_transform != NULL) {
display_transform->applyRGBA(pixel);
}
applyRGB(pixel);
}
TransformType type;
FallbackTransform *linear_transform;
FallbackTransform *display_transform;
/* Scale transform. */
float scale;
/* Exponent transform. */
float exponent[4];
/* Matrix transform. */
float matrix[16];
float offset[4];
float exponent;
MEM_CXX_CLASS_ALLOC_FUNCS("FallbackTransform");
};
struct FallbackGroupTransform : FallbackTransform {
~FallbackGroupTransform()
{
for (auto transform : list) {
delete transform;
}
}
std::vector<FallbackTransform *> list;
};
struct FallbackProcessor {
FallbackProcessor() : transform(NULL)
FallbackProcessor(const FallbackTransform &transform) : transform(transform)
{
}
~FallbackProcessor()
{
delete transform;
}
void applyRGB(float *pixel)
{
transform->applyRGB(pixel);
transform.applyRGB(pixel);
}
void applyRGBA(float *pixel)
{
transform->applyRGBA(pixel);
transform.applyRGBA(pixel);
}
FallbackTransform *transform;
FallbackTransform transform;
MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor");
};
@ -403,30 +328,35 @@ OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstCo
{
OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName);
OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
FallbackTransform *transform = new FallbackTransform();
FallbackTransform transform;
if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) {
transform->type = TRANSFORM_LINEAR_TO_SRGB;
transform.type = TRANSFORM_LINEAR_TO_SRGB;
}
else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) {
transform->type = TRANSFORM_SRGB_TO_LINEAR;
transform.type = TRANSFORM_SRGB_TO_LINEAR;
}
else {
transform->type = TRANSFORM_UNKNOWN;
transform.type = TRANSFORM_UNKNOWN;
}
FallbackProcessor *processor = new FallbackProcessor();
processor->transform = transform;
return (OCIO_ConstProcessorRcPtr *)processor;
return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform);
}
OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/,
OCIO_ConstTransformRcPtr *transform)
OCIO_ConstCPUProcessorRcPtr *FallbackImpl::processorGetCPUProcessor(
OCIO_ConstProcessorRcPtr *processor)
{
FallbackProcessor *processor = new FallbackProcessor();
processor->transform = (FallbackTransform *)transform;
return (OCIO_ConstProcessorRcPtr *)processor;
/* Just make a copy of the processor so that we are compatible with OCIO
* which does need it as a separate object. */
FallbackProcessor *fallback_processor = (FallbackProcessor *)processor;
return (OCIO_ConstCPUProcessorRcPtr *)new FallbackProcessor(*fallback_processor);
}
void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
{
delete (FallbackProcessor *)(processor);
}
void FallbackImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{
/* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img;
@ -441,15 +371,15 @@ void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_Pack
float *pixel = pixels + channels * (y * width + x);
if (channels == 4)
processorApplyRGBA(processor, pixel);
cpuProcessorApplyRGBA(cpu_processor, pixel);
else if (channels == 3)
processorApplyRGB(processor, pixel);
cpuProcessorApplyRGB(cpu_processor, pixel);
}
}
}
void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
OCIO_PackedImageDesc *img)
void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{
/* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img;
@ -464,27 +394,28 @@ void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
float *pixel = pixels + channels * (y * width + x);
if (channels == 4)
processorApplyRGBA_predivide(processor, pixel);
cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
else if (channels == 3)
processorApplyRGB(processor, pixel);
cpuProcessorApplyRGB(cpu_processor, pixel);
}
}
}
void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void FallbackImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
((FallbackProcessor *)processor)->applyRGB(pixel);
((FallbackProcessor *)cpu_processor)->applyRGB(pixel);
}
void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void FallbackImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
((FallbackProcessor *)processor)->applyRGBA(pixel);
((FallbackProcessor *)cpu_processor)->applyRGBA(pixel);
}
void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void FallbackImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
float *pixel)
{
if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
processorApplyRGBA(processor, pixel);
cpuProcessorApplyRGBA(cpu_processor, pixel);
}
else {
float alpha, inv_alpha;
@ -496,7 +427,7 @@ void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *proces
pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha;
processorApplyRGBA(processor, pixel);
cpuProcessorApplyRGBA(cpu_processor, pixel);
pixel[0] *= alpha;
pixel[1] *= alpha;
@ -504,9 +435,9 @@ void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *proces
}
}
void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
void FallbackImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
delete (FallbackProcessor *)(processor);
delete (FallbackProcessor *)(cpu_processor);
}
const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@ -530,54 +461,20 @@ const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr * /*cs*/
return "";
}
OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void)
OCIO_ConstProcessorRcPtr *FallbackImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr * /*config*/,
const char * /*input*/,
const char * /*view*/,
const char * /*display*/,
const char * /*look*/,
const float scale,
const float exponent)
{
FallbackTransform *transform = new FallbackTransform();
transform->type = TRANSFORM_LINEAR_TO_SRGB;
return (OCIO_DisplayTransformRcPtr *)transform;
}
FallbackTransform transform;
transform.type = TRANSFORM_LINEAR_TO_SRGB;
transform.scale = scale;
transform.exponent = exponent;
void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/,
const char * /*name*/)
{
}
void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/,
const char * /*name*/)
{
}
void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/,
const char * /*name*/)
{
}
void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et)
{
FallbackTransform *transform = (FallbackTransform *)dt;
transform->display_transform = (FallbackTransform *)et;
}
void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et)
{
FallbackTransform *transform = (FallbackTransform *)dt;
transform->linear_transform = (FallbackTransform *)et;
}
void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/,
const char * /*looks*/)
{
}
void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/,
bool /*enabled*/)
{
}
void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/)
{
return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform);
}
OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data,
@ -605,127 +502,6 @@ void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
MEM_freeN(id);
}
OCIO_GroupTransformRcPtr *FallbackImpl::createGroupTransform(void)
{
FallbackTransform *transform = new FallbackGroupTransform();
transform->type = TRANSFORM_UNKNOWN;
return (OCIO_GroupTransformRcPtr *)transform;
}
void FallbackImpl::groupTransformSetDirection(OCIO_GroupTransformRcPtr * /*gt*/,
const bool /*forward */)
{
}
void FallbackImpl::groupTransformPushBack(OCIO_GroupTransformRcPtr *gt,
OCIO_ConstTransformRcPtr *transform)
{
FallbackGroupTransform *group = (FallbackGroupTransform *)gt;
group->list.push_back((FallbackTransform *)transform);
}
void FallbackImpl::groupTransformRelease(OCIO_GroupTransformRcPtr * /*gt*/)
{
}
OCIO_ColorSpaceTransformRcPtr *FallbackImpl::createColorSpaceTransform(void)
{
FallbackTransform *transform = new FallbackTransform();
transform->type = TRANSFORM_UNKNOWN;
return (OCIO_ColorSpaceTransformRcPtr *)transform;
}
void FallbackImpl::colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr * /*ct*/,
const char * /*name*/)
{
}
void FallbackImpl::colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr * /*ct*/)
{
}
OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void)
{
FallbackTransform *transform = new FallbackTransform();
transform->type = TRANSFORM_EXPONENT;
return (OCIO_ExponentTransformRcPtr *)transform;
}
void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et,
const float *exponent)
{
FallbackTransform *transform = (FallbackTransform *)et;
copy_v4_v4(transform->exponent, exponent);
}
void FallbackImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr * /*et*/)
{
}
OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void)
{
FallbackTransform *transform = new FallbackTransform();
transform->type = TRANSFORM_MATRIX;
return (OCIO_MatrixTransformRcPtr *)transform;
}
void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4)
{
FallbackTransform *transform = (FallbackTransform *)mt;
copy_m4_m4((float(*)[4])transform->matrix, (float(*)[4])m44);
copy_v4_v4(transform->offset, offset4);
}
void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr * /*mt*/)
{
}
void FallbackImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4)
{
if (scale4 == NULL) {
return;
}
if (m44 != NULL) {
memset(m44, 0, 16 * sizeof(float));
m44[0] = scale4[0];
m44[5] = scale4[1];
m44[10] = scale4[2];
m44[15] = scale4[3];
}
if (offset4 != NULL) {
offset4[0] = 0.0f;
offset4[1] = 0.0f;
offset4[2] = 0.0f;
offset4[3] = 0.0f;
}
}
bool FallbackImpl::supportGLSLDraw(void)
{
return false;
}
bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/,
OCIO_ConstProcessorRcPtr * /*ocio_processor_scene_to_ui*/,
OCIO_ConstProcessorRcPtr * /*ocio_processor_ui_to_display*/,
OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
float /*dither*/,
bool /*predivide*/,
bool /*overlay*/)
{
return false;
}
void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
{
}
void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/)
{
}
const char *FallbackImpl::getVersionString(void)
{
return "fallback";

View File

@ -1,17 +1,18 @@
/* Blender OpenColorIO implementation */
uniform sampler1D curve_mapping_texture;
uniform sampler2D image_texture;
uniform sampler2D overlay_texture;
uniform sampler3D lut3d_texture;
uniform sampler3D lut3d_display_texture;
uniform float dither;
uniform float scale;
uniform float exponent;
uniform bool predivide;
uniform bool curve_mapping;
uniform bool overlay;
layout(std140) uniform OCIO_GLSLCurveMappingParameters
#ifdef USE_CURVE_MAPPING
uniform sampler1D curve_mapping_texture;
layout(std140) uniform OCIO_GPUCurveMappingParameters
{
/* Curve mapping parameters
*
@ -114,6 +115,7 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col)
result.a = col.a;
return result;
}
#endif /* USE_CURVE_MAPPING */
/* Using a triangle distribution which gives a more final uniform noise.
* See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
@ -145,9 +147,9 @@ vec4 apply_dither(vec4 col, vec2 uv)
vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
{
if (curve_mapping) {
col = curvemapping_evaluate_premulRGBF(col);
}
#ifdef USE_CURVE_MAPPING
col = curvemapping_evaluate_premulRGBF(col);
#endif
if (predivide) {
if (col.a > 0.0 && col.a < 1.0) {
@ -160,15 +162,31 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
* for straight alpha at this moment
*/
col = OCIO_to_display_linear_with_look(col, lut3d_texture);
/* Convert to scene linear (usually a no-op). */
col = OCIO_to_scene_linear(col);
/* Apply exposure in scene linear. */
col.rgb *= scale;
/* Convert to display space. */
col = OCIO_to_display(col);
/* Blend with overlay in UI colorspace.
*
* UI colorspace here refers to the display linear color space,
* i.e: The linear color space w.r.t. display chromaticity and radiometry.
* We separate the colormanagement process into two steps to be able to
* merge UI using alpha blending in the correct color space. */
if (overlay) {
col.rgb = pow(col.rgb, vec3(exponent * 2.2));
col = clamp(col, 0.0, 1.0);
col *= 1.0 - col_overlay.a;
col += col_overlay; /* Assumed unassociated alpha. */
col.rgb = pow(col.rgb, vec3(1.0 / 2.2));
}
else {
col.rgb = pow(col.rgb, vec3(exponent));
}
col = OCIO_to_display_encoded(col, lut3d_display_texture);
if (dither > 0.0) {
col = apply_dither(col, noise_uv);
@ -189,4 +207,4 @@ void main()
vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st);
fragColor = OCIO_ProcessColor(col, col_overlay, noise_uv);
}
}

View File

@ -194,40 +194,45 @@ OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr
return impl->configGetProcessorWithNames(config, srcName, dstName);
}
OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform)
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *processor)
{
return impl->configGetProcessor(config, transform);
impl->processorRelease(processor);
}
void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor)
{
impl->processorApply(processor, img);
return impl->processorGetCPUProcessor(processor);
}
void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img)
{
impl->processorApply_predivide(processor, img);
impl->cpuProcessorApply(cpu_processor, img);
}
void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{
impl->processorApplyRGB(processor, pixel);
impl->cpuProcessorApply_predivide(cpu_processor, img);
}
void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIO_cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
impl->processorApplyRGBA(processor, pixel);
impl->cpuProcessorApplyRGB(cpu_processor, pixel);
}
void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIO_cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
impl->processorApplyRGBA_predivide(processor, pixel);
impl->cpuProcessorApplyRGBA(cpu_processor, pixel);
}
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p)
void OCIO_cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *processor, float *pixel)
{
impl->processorRelease(p);
impl->cpuProcessorApplyRGBA_predivide(processor, pixel);
}
void OCIO_cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
impl->cpuProcessorRelease(cpu_processor);
}
const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@ -245,49 +250,15 @@ const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
return impl->colorSpaceGetFamily(cs);
}
OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void)
OCIO_ConstProcessorRcPtr *OCIO_createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent)
{
return impl->createDisplayTransform();
}
void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name)
{
impl->displayTransformSetInputColorSpaceName(dt, name);
}
void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
{
impl->displayTransformSetDisplay(dt, name);
}
void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
{
impl->displayTransformSetView(dt, name);
}
void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
{
impl->displayTransformSetDisplayCC(dt, t);
}
void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
{
impl->displayTransformSetLinearCC(dt, t);
}
void OCIO_displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks)
{
impl->displayTransformSetLooksOverride(dt, looks);
}
void OCIO_displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled)
{
impl->displayTransformSetLooksOverrideEnabled(dt, enabled);
}
void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
{
impl->displayTransformRelease(dt);
return impl->createDisplayProcessor(config, input, view, display, look, scale, exponent);
}
OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
@ -307,108 +278,44 @@ void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
impl->OCIO_PackedImageDescRelease(id);
}
OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void)
bool OCIO_supportGPUShader()
{
return impl->createGroupTransform();
return impl->supportGPUShader();
}
void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward)
bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings,
const float scale,
const float exponent,
const float dither,
const bool use_predivide,
const bool use_overlay)
{
impl->groupTransformSetDirection(gt, forward);
return impl->gpuDisplayShaderBind(config,
input,
view,
display,
look,
curve_mapping_settings,
scale,
exponent,
dither,
use_predivide,
use_overlay);
}
void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr)
void OCIO_gpuDisplayShaderUnbind(void)
{
impl->groupTransformPushBack(gt, tr);
impl->gpuDisplayShaderUnbind();
}
void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt)
void OCIO_gpuCacheFree(void)
{
impl->groupTransformRelease(gt);
}
OCIO_ColorSpaceTransformRcPtr *OCIO_createColorSpaceTransform(void)
{
return impl->createColorSpaceTransform();
}
void OCIO_colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name)
{
impl->colorSpaceTransformSetSrc(ct, name);
}
void OCIO_colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct)
{
impl->colorSpaceTransformRelease(ct);
}
OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void)
{
return impl->createExponentTransform();
}
void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
{
impl->exponentTransformSetValue(et, exponent);
}
void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
{
impl->exponentTransformRelease(et);
}
OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
{
return impl->createMatrixTransform();
}
void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4)
{
impl->matrixTransformSetValue(mt, m44, offset4);
}
void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
{
impl->matrixTransformRelease(mt);
}
void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4f)
{
impl->matrixTransformScale(m44, offset4, scale4f);
}
int OCIO_supportGLSLDraw(void)
{
return (int)impl->supportGLSLDraw();
}
int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool predivide,
bool overlay)
{
return (int)impl->setupGLSLDraw(state_r,
ocio_processor_scene_to_ui,
ocio_processor_ui_to_display,
curve_mapping_settings,
dither,
predivide,
overlay);
}
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
{
impl->finishGLSLDraw(state);
}
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state)
{
impl->freeGLState(state);
impl->gpuCacheFree();
}
const char *OCIO_getVersionString(void)

View File

@ -24,7 +24,7 @@
extern "C" {
#endif
struct OCIO_GLSLDrawState;
typedef struct OCIO_GPUShader OCIO_GPUShader;
#define OCIO_DECLARE_HANDLE(name) \
typedef struct name##__ { \
@ -42,14 +42,9 @@ struct OCIO_GLSLDrawState;
OCIO_DECLARE_HANDLE(OCIO_ConstConfigRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstColorSpaceRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstProcessorRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstCPUProcessorRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr);
OCIO_DECLARE_HANDLE(OCIO_PackedImageDesc);
OCIO_DECLARE_HANDLE(OCIO_DisplayTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ColorSpaceTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_GroupTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr);
/* Standard XYZ to linear sRGB transform, for fallback. */
@ -163,32 +158,28 @@ void OCIO_lookRelease(OCIO_ConstLookRcPtr *look);
OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName,
const char *dstName);
OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform);
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *cpu_processor);
void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p);
OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img);
void OCIO_cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void OCIO_cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void OCIO_cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void OCIO_cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *processor);
const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void);
void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name);
void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name);
void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name);
void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et);
void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et);
void OCIO_displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks);
void OCIO_displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled);
void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_ConstProcessorRcPtr *OCIO_createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent);
OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
long width,
@ -200,37 +191,20 @@ OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void);
void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward);
void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr);
void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt);
OCIO_ColorSpaceTransformRcPtr *OCIO_createColorSpaceTransform(void);
void OCIO_colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name);
void OCIO_colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct);
OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void);
void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent);
void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et);
OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void);
void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4);
void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4);
int OCIO_supportGLSLDraw(void);
int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool predivide,
bool overlay);
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
bool OCIO_supportGPUShader(void);
bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings,
const float scale,
const float exponent,
const float dither,
const bool use_predivide,
const bool use_overlay);
void OCIO_gpuDisplayShaderUnbind(void);
void OCIO_gpuCacheFree(void);
const char *OCIO_getVersionString(void);
int OCIO_getVersionHex(void);

View File

@ -17,6 +17,7 @@
* All rights reserved.
*/
#include <cassert>
#include <iostream>
#include <math.h>
#include <sstream>
@ -35,7 +36,9 @@ using namespace OCIO_NAMESPACE;
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "ocio_impl.h"
@ -267,7 +270,7 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf
const char *view)
{
try {
return (*(ConstConfigRcPtr *)config)->getDisplayColorSpaceName(display, view);
return (*(ConstConfigRcPtr *)config)->getDisplayViewColorSpaceName(display, view);
}
catch (Exception &exception) {
OCIO_reportException(exception);
@ -279,13 +282,46 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf
void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
{
try {
(*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb);
double rgb_double[3];
(*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb_double);
rgb[0] = rgb_double[0];
rgb[1] = rgb_double[1];
rgb[2] = rgb_double[2];
}
catch (Exception &exception) {
OCIO_reportException(exception);
}
}
static bool to_scene_linear_matrix(ConstConfigRcPtr &config,
const char *colorspace,
float to_scene_linear[3][3])
{
ConstProcessorRcPtr processor;
try {
processor = config->getProcessor(colorspace, ROLE_SCENE_LINEAR);
}
catch (Exception &exception) {
OCIO_reportException(exception);
return false;
}
if (!processor) {
return false;
}
ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
if (!cpu_processor) {
return false;
}
unit_m3(to_scene_linear);
cpu_processor->applyRGB(to_scene_linear[0]);
cpu_processor->applyRGB(to_scene_linear[1]);
cpu_processor->applyRGB(to_scene_linear[2]);
return true;
}
void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rgb[3][3])
{
ConstConfigRcPtr config = (*(ConstConfigRcPtr *)config_);
@ -293,24 +329,25 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg
/* Default to ITU-BT.709 in case no appropriate transform found. */
memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB));
/* Auto estimate from XYZ and scene_linear roles, assumed to be a linear transform. */
if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
if (to_rgb_processor) {
xyz_to_rgb[0][0] = 1.0f;
xyz_to_rgb[0][1] = 0.0f;
xyz_to_rgb[0][2] = 0.0f;
xyz_to_rgb[1][0] = 0.0f;
xyz_to_rgb[1][1] = 1.0f;
xyz_to_rgb[1][2] = 0.0f;
xyz_to_rgb[2][0] = 0.0f;
xyz_to_rgb[2][1] = 0.0f;
xyz_to_rgb[2][2] = 1.0f;
to_rgb_processor->applyRGB(xyz_to_rgb[0]);
to_rgb_processor->applyRGB(xyz_to_rgb[1]);
to_rgb_processor->applyRGB(xyz_to_rgb[2]);
/* Get from OpenColorO config if it has the required roles. */
if (!config->hasRole(ROLE_SCENE_LINEAR)) {
return;
}
if (config->hasRole("aces_interchange")) {
/* Standard OpenColorIO role, defined as ACES2065-1. */
const float xyz_to_aces[3][3] = {{1.0498110175f, -0.4959030231f, 0.0f},
{0.0f, 1.3733130458f, 0.0f},
{-0.0000974845f, 0.0982400361f, 0.9912520182f}};
float aces_to_rgb[3][3];
if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) {
mul_m3_m3m3(xyz_to_rgb, aces_to_rgb, xyz_to_aces);
}
}
else if (config->hasRole("XYZ")) {
/* Custom role used before the standard existed. */
to_scene_linear_matrix(config, "XYZ", xyz_to_rgb);
}
}
int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
@ -431,6 +468,8 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
return;
}
ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
is_scene_linear = true;
is_srgb = true;
for (int i = 0; i < 256; i++) {
@ -440,10 +479,10 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
float cG[3] = {0, v, 0};
float cB[3] = {0, 0, v};
float cW[3] = {v, v, v};
processor->applyRGB(cR);
processor->applyRGB(cG);
processor->applyRGB(cB);
processor->applyRGB(cW);
cpu_processor->applyRGB(cR);
cpu_processor->applyRGB(cG);
cpu_processor->applyRGB(cB);
cpu_processor->applyRGB(cW);
/* Make sure that there is no channel crosstalk. */
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
@ -485,62 +524,57 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfig
const char *srcName,
const char *dstName)
{
ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
ConstProcessorRcPtr *processor = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
try {
*p = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
*processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
if (*p)
return (OCIO_ConstProcessorRcPtr *)p;
if (*processor)
return (OCIO_ConstProcessorRcPtr *)processor;
}
catch (Exception &exception) {
OCIO_reportException(exception);
}
OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr);
return 0;
}
OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform)
void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
{
ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
try {
*p = (*(ConstConfigRcPtr *)config)->getProcessor(*(ConstTransformRcPtr *)transform);
if (*p)
return (OCIO_ConstProcessorRcPtr *)p;
}
catch (Exception &exception) {
OCIO_reportException(exception);
}
OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
return NULL;
OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr);
}
void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
OCIO_ConstCPUProcessorRcPtr *OCIOImpl::processorGetCPUProcessor(
OCIO_ConstProcessorRcPtr *processor)
{
ConstCPUProcessorRcPtr *cpu_processor = OBJECT_GUARDED_NEW(ConstCPUProcessorRcPtr);
*cpu_processor = (*(ConstProcessorRcPtr *)processor)->getDefaultCPUProcessor();
return (OCIO_ConstCPUProcessorRcPtr *)cpu_processor;
}
void OCIOImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{
try {
(*(ConstProcessorRcPtr *)processor)->apply(*(PackedImageDesc *)img);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*(PackedImageDesc *)img);
}
catch (Exception &exception) {
OCIO_reportException(exception);
}
}
void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
OCIO_PackedImageDesc *img_)
void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img_)
{
try {
PackedImageDesc *img = (PackedImageDesc *)img_;
int channels = img->getNumChannels();
if (channels == 4) {
float *pixels = img->getData();
assert(img->isFloat());
float *pixels = (float *)img->getData();
int width = img->getWidth();
int height = img->getHeight();
@ -549,12 +583,12 @@ void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
for (int x = 0; x < width; x++) {
float *pixel = pixels + 4 * (y * width + x);
processorApplyRGBA_predivide(processor, pixel);
cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
}
}
}
else {
(*(ConstProcessorRcPtr *)processor)->apply(*img);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*img);
}
}
catch (Exception &exception) {
@ -562,20 +596,21 @@ void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
}
}
void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIOImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
(*(ConstProcessorRcPtr *)processor)->applyRGB(pixel);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGB(pixel);
}
void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIOImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
(*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
}
void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
void OCIOImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
float *pixel)
{
if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
(*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
}
else {
float alpha, inv_alpha;
@ -587,7 +622,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha;
(*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel);
(*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
pixel[0] *= alpha;
pixel[1] *= alpha;
@ -595,9 +630,9 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
}
}
void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
void OCIOImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
OBJECT_GUARDED_DELETE(cpu_processor, ConstCPUProcessorRcPtr);
}
const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@ -615,57 +650,85 @@ const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
}
OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
OCIO_ConstProcessorRcPtr *OCIOImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr *config_,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent)
{
DisplayTransformRcPtr *dt = OBJECT_GUARDED_NEW(DisplayTransformRcPtr);
ConstConfigRcPtr config = *(ConstConfigRcPtr *)config_;
GroupTransformRcPtr group = GroupTransform::Create();
*dt = DisplayTransform::Create();
/* Exposure. */
if (scale != 1.0f) {
/* Always apply exposure in scene linear. */
ColorSpaceTransformRcPtr ct = ColorSpaceTransform::Create();
ct->setSrc(input);
ct->setDst(ROLE_SCENE_LINEAR);
group->appendTransform(ct);
return (OCIO_DisplayTransformRcPtr *)dt;
}
/* Make further transforms aware of the color space change. */
input = ROLE_SCENE_LINEAR;
void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt,
const char *name)
{
(*(DisplayTransformRcPtr *)dt)->setInputColorSpaceName(name);
}
/* Apply scale. */
MatrixTransformRcPtr mt = MatrixTransform::Create();
const double matrix[16] = {
scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, 1.0};
mt->setMatrix(matrix);
group->appendTransform(mt);
}
void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
{
(*(DisplayTransformRcPtr *)dt)->setDisplay(name);
}
/* Add look transform. */
const bool use_look = (strlen(look) != 0);
if (use_look) {
const char *look_output = LookTransform::GetLooksResultColorSpace(
config, config->getCurrentContext(), look);
void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
{
(*(DisplayTransformRcPtr *)dt)->setView(name);
}
LookTransformRcPtr lt = LookTransform::Create();
lt->setSrc(input);
lt->setDst(look_output);
lt->setLooks(look);
group->appendTransform(lt);
void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *t)
{
(*(DisplayTransformRcPtr *)dt)->setDisplayCC(*(ConstTransformRcPtr *)t);
}
/* Make further transforms aware of the color space change. */
input = look_output;
}
void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *t)
{
(*(DisplayTransformRcPtr *)dt)->setLinearCC(*(ConstTransformRcPtr *)t);
}
/* Add view and display transform. */
DisplayViewTransformRcPtr dvt = DisplayViewTransform::Create();
dvt->setSrc(input);
dvt->setLooksBypass(use_look);
dvt->setView(view);
dvt->setDisplay(display);
group->appendTransform(dvt);
void OCIOImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks)
{
(*(DisplayTransformRcPtr *)dt)->setLooksOverride(looks);
}
/* Gamma. */
if (exponent != 1.0f) {
ExponentTransformRcPtr et = ExponentTransform::Create();
const double value[4] = {exponent, exponent, exponent, 1.0};
et->setValue(value);
group->appendTransform(et);
}
void OCIOImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt,
bool enabled)
{
(*(DisplayTransformRcPtr *)dt)->setLooksOverrideEnabled(enabled);
}
/* Create processor from transform. This is the moment were OCIO validates
* the entire transform, no need to check for the validity of inputs above. */
ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
{
OBJECT_GUARDED_DELETE((DisplayTransformRcPtr *)dt, DisplayTransformRcPtr);
try {
*p = config->getProcessor(group);
if (*p)
return (OCIO_ConstProcessorRcPtr *)p;
}
catch (Exception &exception) {
OCIO_reportException(exception);
}
OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
return NULL;
}
OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
@ -678,8 +741,14 @@ OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
{
try {
void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
PackedImageDesc *id = new (mem) PackedImageDesc(
data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
PackedImageDesc *id = new (mem) PackedImageDesc(data,
width,
height,
numChannels,
BIT_DEPTH_F32,
chanStrideBytes,
xStrideBytes,
yStrideBytes);
return (OCIO_PackedImageDesc *)id;
}
@ -695,96 +764,6 @@ void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
OBJECT_GUARDED_DELETE((PackedImageDesc *)id, PackedImageDesc);
}
OCIO_GroupTransformRcPtr *OCIOImpl::createGroupTransform(void)
{
GroupTransformRcPtr *gt = OBJECT_GUARDED_NEW(GroupTransformRcPtr);
*gt = GroupTransform::Create();
return (OCIO_GroupTransformRcPtr *)gt;
}
void OCIOImpl::groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward)
{
TransformDirection dir = forward ? TRANSFORM_DIR_FORWARD : TRANSFORM_DIR_INVERSE;
(*(GroupTransformRcPtr *)gt)->setDirection(dir);
}
void OCIOImpl::groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr)
{
(*(GroupTransformRcPtr *)gt)->push_back(*(ConstTransformRcPtr *)tr);
}
void OCIOImpl::groupTransformRelease(OCIO_GroupTransformRcPtr *gt)
{
OBJECT_GUARDED_DELETE((GroupTransformRcPtr *)gt, GroupTransformRcPtr);
}
OCIO_ColorSpaceTransformRcPtr *OCIOImpl::createColorSpaceTransform(void)
{
ColorSpaceTransformRcPtr *ct = OBJECT_GUARDED_NEW(ColorSpaceTransformRcPtr);
*ct = ColorSpaceTransform::Create();
(*ct)->setDirection(TRANSFORM_DIR_FORWARD);
return (OCIO_ColorSpaceTransformRcPtr *)ct;
}
void OCIOImpl::colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name)
{
(*(ColorSpaceTransformRcPtr *)ct)->setSrc(name);
}
void OCIOImpl::colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct)
{
OBJECT_GUARDED_DELETE((ColorSpaceTransformRcPtr *)ct, ColorSpaceTransformRcPtr);
}
OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
{
ExponentTransformRcPtr *et = OBJECT_GUARDED_NEW(ExponentTransformRcPtr);
*et = ExponentTransform::Create();
return (OCIO_ExponentTransformRcPtr *)et;
}
void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
{
(*(ExponentTransformRcPtr *)et)->setValue(exponent);
}
void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
{
OBJECT_GUARDED_DELETE((ExponentTransformRcPtr *)et, ExponentTransformRcPtr);
}
OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
{
MatrixTransformRcPtr *mt = OBJECT_GUARDED_NEW(MatrixTransformRcPtr);
*mt = MatrixTransform::Create();
return (OCIO_MatrixTransformRcPtr *)mt;
}
void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4)
{
(*(MatrixTransformRcPtr *)mt)->setValue(m44, offset4);
}
void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
{
OBJECT_GUARDED_DELETE((MatrixTransformRcPtr *)mt, MatrixTransformRcPtr);
}
void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4f)
{
MatrixTransform::Scale(m44, offset4, scale4f);
}
const char *OCIOImpl::getVersionString(void)
{
return GetVersion();

View File

@ -76,36 +76,30 @@ class IOCIOImpl {
virtual OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName,
const char *dstName) = 0;
virtual OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform) = 0;
virtual void processorRelease(OCIO_ConstProcessorRcPtr *processor) = 0;
virtual void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) = 0;
virtual void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
OCIO_PackedImageDesc *img) = 0;
virtual void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0;
virtual void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0;
virtual void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0;
virtual void processorRelease(OCIO_ConstProcessorRcPtr *p) = 0;
virtual OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *p) = 0;
virtual void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img) = 0;
virtual void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img) = 0;
virtual void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0;
virtual void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0;
virtual void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
float *pixel) = 0;
virtual void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor) = 0;
virtual const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual OCIO_DisplayTransformRcPtr *createDisplayTransform(void) = 0;
virtual void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt,
const char *name) = 0;
virtual void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0;
virtual void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0;
virtual void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et) = 0;
virtual void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt,
OCIO_ConstTransformRcPtr *et) = 0;
virtual void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt,
const char *looks) = 0;
virtual void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt,
bool enabled) = 0;
virtual void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) = 0;
virtual OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent) = 0;
virtual OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width,
@ -117,39 +111,31 @@ class IOCIOImpl {
virtual void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p) = 0;
virtual OCIO_GroupTransformRcPtr *createGroupTransform(void) = 0;
virtual void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) = 0;
virtual void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt,
OCIO_ConstTransformRcPtr *transform) = 0;
virtual void groupTransformRelease(OCIO_GroupTransformRcPtr *gt) = 0;
virtual OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void) = 0;
virtual void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name) = 0;
virtual void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct) = 0;
virtual OCIO_ExponentTransformRcPtr *createExponentTransform(void) = 0;
virtual void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et,
const float *exponent) = 0;
virtual void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) = 0;
virtual OCIO_MatrixTransformRcPtr *createMatrixTransform(void) = 0;
virtual void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4) = 0;
virtual void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) = 0;
virtual void matrixTransformScale(float *m44, float *offset4, const float *scale4) = 0;
virtual bool supportGLSLDraw(void) = 0;
virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool predivide,
bool overlay) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
/* Optional GPU support. */
virtual bool supportGPUShader()
{
return false;
}
virtual bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr * /*config*/,
const char * /*input*/,
const char * /*view*/,
const char * /*display*/,
const char * /*look*/,
OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
const float /*scale*/,
const float /*exponent*/,
const float /*dither*/,
const bool /*use_predivide*/,
const bool /*use_overlay*/)
{
return false;
}
virtual void gpuDisplayShaderUnbind(void)
{
}
virtual void gpuCacheFree(void)
{
}
virtual const char *getVersionString(void) = 0;
virtual int getVersionHex(void) = 0;
@ -206,30 +192,28 @@ class FallbackImpl : public IOCIOImpl {
OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName,
const char *dstName);
OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform);
void processorRelease(OCIO_ConstProcessorRcPtr *processor);
void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorRelease(OCIO_ConstProcessorRcPtr *p);
OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img);
void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *createDisplayTransform(void);
void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et);
void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et);
void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks);
void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled);
void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent);
OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width,
@ -241,38 +225,6 @@ class FallbackImpl : public IOCIOImpl {
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_GroupTransformRcPtr *createGroupTransform(void);
void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward);
void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *transform);
void groupTransformRelease(OCIO_GroupTransformRcPtr *gt);
OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void);
void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name);
void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct);
OCIO_ExponentTransformRcPtr *createExponentTransform(void);
void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent);
void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et);
OCIO_MatrixTransformRcPtr *createMatrixTransform(void);
void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4);
void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void matrixTransformScale(float *m44, float *offset4, const float *scale4);
bool supportGLSLDraw(void);
bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool predivide,
bool overlay);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
const char *getVersionString(void);
int getVersionHex(void);
};
@ -327,30 +279,28 @@ class OCIOImpl : public IOCIOImpl {
OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName,
const char *dstName);
OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config,
OCIO_ConstTransformRcPtr *transform);
void processorRelease(OCIO_ConstProcessorRcPtr *processor);
void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img);
void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel);
void processorRelease(OCIO_ConstProcessorRcPtr *p);
OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img);
void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *createDisplayTransform(void);
void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name);
void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et);
void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et);
void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks);
void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled);
void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
const float scale,
const float exponent);
OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width,
@ -362,37 +312,20 @@ class OCIOImpl : public IOCIOImpl {
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_GroupTransformRcPtr *createGroupTransform(void);
void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward);
void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *transform);
void groupTransformRelease(OCIO_GroupTransformRcPtr *gt);
OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void);
void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name);
void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct);
OCIO_ExponentTransformRcPtr *createExponentTransform(void);
void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent);
void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et);
OCIO_MatrixTransformRcPtr *createMatrixTransform(void);
void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
const float *m44,
const float *offset4);
void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void matrixTransformScale(float *m44, float *offset4, const float *scale4);
bool supportGLSLDraw(void);
bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool predivide,
bool overlay);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
bool supportGPUShader();
bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings,
const float scale,
const float exponent,
const float dither,
const bool use_predivide,
const bool use_overlay);
void gpuDisplayShaderUnbind(void);
void gpuCacheFree(void);
const char *getVersionString(void);
int getVersionHex(void);

View File

@ -31,8 +31,10 @@
*/
#include <limits>
#include <list>
#include <sstream>
#include <string.h>
#include <vector>
#ifdef _MSC_VER
# pragma warning(push)
@ -53,24 +55,24 @@ using namespace OCIO_NAMESPACE;
#include "ocio_impl.h"
static const int LUT3D_EDGE_SIZE = 64;
static const int LUT3D_TEXTURE_SIZE = sizeof(float) * 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE *
LUT3D_EDGE_SIZE;
static const int SHADER_CACHE_SIZE = 4;
#define UBO_BIND_LOC 0
extern "C" char datatoc_gpu_shader_display_transform_glsl[];
extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
enum OCIO_GPUTextureSlots {
TEXTURE_SLOT_IMAGE = 0,
TEXTURE_SLOT_OVERLAY = 1,
TEXTURE_SLOT_CURVE_MAPPING = 2,
TEXTURE_SLOT_LUTS_OFFSET = 3,
};
/* Curve mapping parameters
*
* See documentation for OCIO_CurveMappingSettings to get fields descriptions.
* (this ones pretty much copies stuff from C structure.)
*/
struct OCIO_GLSLCurveMappingParameters {
struct OCIO_GPUCurveMappingParameters {
float curve_mapping_mintable[4];
float curve_mapping_range[4];
float curve_mapping_ext_in_x[4];
@ -89,79 +91,108 @@ struct OCIO_GLSLCurveMappingParameters {
/** WARNING: Needs to be 16byte aligned. Used as UBO data. */
};
struct OCIO_GLSLShader {
/** Cache IDs */
std::string cacheId;
struct OCIO_GPUShader {
/* GPU shader. */
struct GPUShader *shader = nullptr;
struct GPUShader *shader;
/** Uniform locations. */
int dither_loc;
int overlay_loc;
int predivide_loc;
int curve_mapping_loc;
int ubo_bind;
/** Error checking. */
bool valid;
int scale_loc = 0;
int exponent_loc = 0;
int dither_loc = 0;
int overlay_loc = 0;
int predivide_loc = 0;
int ubo_bind = 0;
/* Destructor. */
~OCIO_GPUShader()
{
if (shader) {
GPU_shader_free(shader);
}
}
};
struct OCIO_GLSLLut3d {
/** Cache IDs */
std::string cacheId;
/** OpenGL Texture handles. NULL if not allocated. */
GPUTexture *texture;
GPUTexture *texture_display;
GPUTexture *texture_dummy;
/** Error checking. */
bool valid;
struct OCIO_GPULutTexture {
GPUTexture *texture = nullptr;
std::string sampler_name;
};
struct OCIO_GLSLCurveMappping {
/** Cache IDs */
size_t cacheId;
struct OCIO_GPUUniform {
GpuShaderDesc::UniformData data;
std::string name;
};
struct OCIO_GPUTextures {
/** LUT Textures */
std::vector<OCIO_GPULutTexture> luts;
/* Dummy in case of no overlay. */
GPUTexture *dummy = nullptr;
/* Uniforms */
std::vector<OCIO_GPUUniform> uniforms;
/* Destructor. */
~OCIO_GPUTextures()
{
for (OCIO_GPULutTexture &lut : luts) {
GPU_texture_free(lut.texture);
}
if (dummy) {
GPU_texture_free(dummy);
}
}
};
struct OCIO_GPUCurveMappping {
/** GPU Uniform Buffer handle. 0 if not allocated. */
GPUUniformBuf *buffer;
GPUUniformBuf *buffer = nullptr;
/** OpenGL Texture handles. 0 if not allocated. */
GPUTexture *texture;
GPUTexture *texture = nullptr;
/* To detect when to update the uniforms and textures. */
size_t cache_id = 0;
/* Destructor. */
~OCIO_GPUCurveMappping()
{
if (texture) {
GPU_texture_free(texture);
}
if (buffer) {
GPU_uniformbuf_free(buffer);
}
}
};
struct OCIO_GPUDisplayShader {
OCIO_GPUShader shader;
OCIO_GPUTextures textures;
OCIO_GPUCurveMappping curvemap;
/* Cache variables. */
std::string input;
std::string view;
std::string display;
std::string look;
bool use_curve_mapping = false;
/** Error checking. */
bool valid;
bool valid = false;
};
struct OCIO_GLSLCacheHandle {
size_t cache_id;
void *data;
};
struct OCIO_GLSLDrawState {
/* Shader Cache */
OCIO_GLSLCacheHandle shader_cache[SHADER_CACHE_SIZE];
OCIO_GLSLCacheHandle lut3d_cache[SHADER_CACHE_SIZE];
OCIO_GLSLCacheHandle curvemap_cache[SHADER_CACHE_SIZE];
};
static OCIO_GLSLDrawState *allocateOpenGLState(void)
{
return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct");
}
static const int SHADER_CACHE_MAX_SIZE = 4;
std::list<OCIO_GPUDisplayShader> SHADER_CACHE;
/* -------------------------------------------------------------------- */
/** \name Shader
* \{ */
static void updateGLSLShader(OCIO_GLSLShader *shader,
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display,
GpuShaderDesc *shader_desc,
const std::string &cache_id)
static bool createGPUShader(OCIO_GPUShader &shader,
OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shaderdesc_to_scene_linear,
const GpuShaderDescRcPtr &shaderdesc_to_display,
const bool use_curve_mapping)
{
if (shader->cacheId == cache_id) {
return;
}
/* Delete any previous shader. */
if (shader->shader) {
GPU_shader_free(shader->shader);
}
std::ostringstream os;
{
/* Fragment shader */
@ -170,146 +201,222 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
os << "#define texture2D texture\n";
os << "#define texture3D texture\n";
shader_desc->setFunctionName("OCIO_to_display_linear_with_look");
os << (*processor_scene_to_ui)->getGpuShaderText(*shader_desc) << "\n";
if (use_curve_mapping) {
os << "#define USE_CURVE_MAPPING\n";
}
shader_desc->setFunctionName("OCIO_to_display_encoded");
os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n";
os << shaderdesc_to_scene_linear->getShaderText() << "\n";
os << shaderdesc_to_display->getShaderText() << "\n";
os << datatoc_gpu_shader_display_transform_glsl;
}
shader->shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
os.str().c_str(),
NULL,
NULL,
NULL,
"OCIOShader");
shader.shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
os.str().c_str(),
nullptr,
nullptr,
nullptr,
"OCIOShader");
if (shader->shader) {
shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither");
shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay");
shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide");
shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping");
shader->ubo_bind = GPU_shader_get_uniform_block_binding(shader->shader,
"OCIO_GLSLCurveMappingParameters");
GPU_shader_bind(shader->shader);
/* Set texture bind point uniform once. This is saved by the shader. */
GPUShader *sh = shader->shader;
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0);
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), 1);
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2);
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3);
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4);
if (shader.shader == nullptr) {
return false;
}
shader->cacheId = cache_id;
shader->valid = (shader->shader != NULL);
}
shader.scale_loc = GPU_shader_get_uniform(shader.shader, "scale");
shader.exponent_loc = GPU_shader_get_uniform(shader.shader, "exponent");
shader.dither_loc = GPU_shader_get_uniform(shader.shader, "dither");
shader.overlay_loc = GPU_shader_get_uniform(shader.shader, "overlay");
shader.predivide_loc = GPU_shader_get_uniform(shader.shader, "predivide");
shader.ubo_bind = GPU_shader_get_uniform_block_binding(shader.shader,
"OCIO_GPUCurveMappingParameters");
static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr,
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display,
GpuShaderDesc *shader_desc,
const std::string &cache_id)
{
if (*shader_ptr != NULL) {
return;
GPU_shader_bind(shader.shader);
/* Set texture bind point uniform once. This is saved by the shader. */
GPUShader *sh = shader.shader;
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), TEXTURE_SLOT_IMAGE);
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), TEXTURE_SLOT_OVERLAY);
if (use_curve_mapping) {
GPU_shader_uniform_int(
sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), TEXTURE_SLOT_CURVE_MAPPING);
}
OCIO_GLSLShader *shader = OBJECT_GUARDED_NEW(OCIO_GLSLShader);
updateGLSLShader(shader, processor_scene_to_ui, processpr_ui_to_display, shader_desc, cache_id);
*shader_ptr = shader;
}
static void freeGLSLShader(OCIO_GLSLShader *shader)
{
if (shader->shader) {
GPU_shader_free(shader->shader);
/* Set LUT textures. */
for (int i = 0; i < textures.luts.size(); i++) {
GPU_shader_uniform_int(sh,
GPU_shader_get_uniform(sh, textures.luts[i].sampler_name.c_str()),
TEXTURE_SLOT_LUTS_OFFSET + i);
}
OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader);
/* Set uniforms. */
for (OCIO_GPUUniform &uniform : textures.uniforms) {
const GpuShaderDesc::UniformData &data = uniform.data;
const char *name = name;
if (data.m_getDouble) {
GPU_shader_uniform_1f(sh, name, (float)data.m_getDouble());
}
else if (data.m_getBool) {
GPU_shader_uniform_1f(sh, name, (float)(data.m_getBool() ? 1.0f : 0.0f));
}
else if (data.m_getFloat3) {
GPU_shader_uniform_3f(sh,
name,
(float)data.m_getFloat3()[0],
(float)data.m_getFloat3()[1],
(float)data.m_getFloat3()[2]);
}
else if (data.m_vectorFloat.m_getSize && data.m_vectorFloat.m_getVector) {
GPU_shader_uniform_vector(sh,
GPU_shader_get_uniform(sh, name),
(int)data.m_vectorFloat.m_getSize(),
1,
(float *)data.m_vectorFloat.m_getVector());
}
else if (data.m_vectorInt.m_getSize && data.m_vectorInt.m_getVector) {
GPU_shader_uniform_vector_int(sh,
GPU_shader_get_uniform(sh, name),
(int)data.m_vectorInt.m_getSize(),
1,
(int *)data.m_vectorInt.m_getVector());
}
}
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lut3D
/** \name Textures
* \{ */
static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d,
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display,
GpuShaderDesc *shader_desc,
const std::string &cache_id)
static bool addGPUUniform(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shader_desc,
int index)
{
if (lut3d->cacheId == cache_id)
return;
float *lut_data = (float *)MEM_mallocN(LUT3D_TEXTURE_SIZE, __func__);
ConstProcessorRcPtr *ocio_processors[2] = {processor_scene_to_ui, processpr_ui_to_display};
for (int i = 0; i < 2; i++) {
ConstProcessorRcPtr *processor = ocio_processors[i];
GPUTexture *texture = (&lut3d->texture)[i];
(*processor)->getGpuLut3D(lut_data, *shader_desc);
int offset[3] = {0, 0, 0};
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
GPU_texture_update_sub(texture, GPU_DATA_FLOAT, lut_data, UNPACK3(offset), UNPACK3(extent));
OCIO_GPUUniform uniform;
uniform.name = shader_desc->getUniform(index, uniform.data);
if (uniform.data.m_type == UNIFORM_UNKNOWN) {
return false;
}
MEM_freeN(lut_data);
lut3d->cacheId = cache_id;
textures.uniforms.push_back(uniform);
return true;
}
static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr,
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display,
GpuShaderDesc *shaderDesc,
const std::string &cache_id)
static bool addGPULut2D(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shader_desc,
int index)
{
if (*lut3d_ptr != NULL) {
return;
const char *texture_name = nullptr;
const char *sampler_name = nullptr;
unsigned int width = 0;
unsigned int height = 0;
GpuShaderCreator::TextureType channel = GpuShaderCreator::TEXTURE_RGB_CHANNEL;
Interpolation interpolation = INTERP_LINEAR;
shader_desc->getTexture(
index, texture_name, sampler_name, width, height, channel, interpolation);
const float *values;
shader_desc->getTextureValues(index, values);
if (texture_name == nullptr || sampler_name == nullptr || width == 0 || height == 0 ||
values == nullptr) {
return false;
}
OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d);
eGPUTextureFormat format = (channel == GpuShaderCreator::TEXTURE_RGB_CHANNEL) ? GPU_RGB16F :
GPU_R16F;
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_2d(texture_name, width, height, 0, format, values);
if (lut.texture == nullptr) {
return false;
}
lut3d->texture = GPU_texture_create_3d(
"OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
GPU_texture_filter_mode(lut3d->texture, true);
GPU_texture_wrap_mode(lut3d->texture, false, true);
GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST);
GPU_texture_wrap_mode(lut.texture, false, true);
lut3d->texture_display = GPU_texture_create_3d(
"OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
GPU_texture_filter_mode(lut3d->texture_display, true);
GPU_texture_wrap_mode(lut3d->texture_display, false, true);
lut.sampler_name = sampler_name;
lut3d->texture_dummy = GPU_texture_create_error(2, false);
updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id);
lut3d->valid = (lut3d->texture && lut3d->texture_display);
*lut3d_ptr = lut3d;
textures.luts.push_back(lut);
return true;
}
static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
static bool addGPULut3D(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shader_desc,
int index)
{
GPU_texture_free(lut3d->texture);
GPU_texture_free(lut3d->texture_display);
GPU_texture_free(lut3d->texture_dummy);
const char *texture_name = nullptr;
const char *sampler_name = nullptr;
unsigned int edgelen = 0;
Interpolation interpolation = INTERP_LINEAR;
shader_desc->get3DTexture(index, texture_name, sampler_name, edgelen, interpolation);
OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d);
const float *values;
shader_desc->get3DTextureValues(index, values);
if (texture_name == nullptr || sampler_name == nullptr || edgelen == 0 || values == nullptr) {
return false;
}
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_3d(
texture_name, edgelen, edgelen, edgelen, 0, GPU_RGB16F, GPU_DATA_FLOAT, values);
if (lut.texture == nullptr) {
return false;
}
GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST);
GPU_texture_wrap_mode(lut.texture, false, true);
lut.sampler_name = sampler_name;
textures.luts.push_back(lut);
return true;
}
static bool createGPUTextures(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shaderdesc_to_scene_linear,
const GpuShaderDescRcPtr &shaderdesc_to_display)
{
textures.dummy = GPU_texture_create_error(2, false);
textures.luts.clear();
textures.uniforms.clear();
for (int index = 0; index < shaderdesc_to_scene_linear->getNumUniforms(); index++) {
if (!addGPUUniform(textures, shaderdesc_to_scene_linear, index)) {
return false;
}
}
for (int index = 0; index < shaderdesc_to_scene_linear->getNumTextures(); index++) {
if (!addGPULut2D(textures, shaderdesc_to_scene_linear, index)) {
return false;
}
}
for (int index = 0; index < shaderdesc_to_scene_linear->getNum3DTextures(); index++) {
if (!addGPULut3D(textures, shaderdesc_to_scene_linear, index)) {
return false;
}
}
for (int index = 0; index < shaderdesc_to_display->getNumUniforms(); index++) {
if (!addGPUUniform(textures, shaderdesc_to_display, index)) {
return false;
}
}
for (int index = 0; index < shaderdesc_to_display->getNumTextures(); index++) {
if (!addGPULut2D(textures, shaderdesc_to_display, index)) {
return false;
}
}
for (int index = 0; index < shaderdesc_to_display->getNum3DTextures(); index++) {
if (!addGPULut3D(textures, shaderdesc_to_display, index)) {
return false;
}
}
return true;
}
/** \} */
@ -317,72 +424,47 @@ static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
/* -------------------------------------------------------------------- */
/** \name Curve Mapping
* \{ */
static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings)
static bool createGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings)
{
int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1;
/* Do not initialize. Only if used. */
curvemap->texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL);
GPU_texture_filter_mode(curvemap->texture, false);
GPU_texture_wrap_mode(curvemap->texture, false, true);
if (curve_mapping_settings) {
int lut_size = curve_mapping_settings->lut_size;
curvemap.texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, nullptr);
GPU_texture_filter_mode(curvemap.texture, false);
GPU_texture_wrap_mode(curvemap.texture, false, true);
curvemap.buffer = GPU_uniformbuf_create(sizeof(OCIO_GPUCurveMappingParameters));
if (curvemap.texture == nullptr || curvemap.buffer == nullptr) {
return false;
}
}
return true;
}
/* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */
static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr,
OCIO_CurveMappingSettings *curve_mapping_settings)
static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings)
{
if (*curvemap_ptr != NULL) {
/* Test if we need to update. The caller ensures the curve_mapping_settings
* changes when its contents changes. */
if (curve_mapping_settings == nullptr || curvemap.cache_id == curve_mapping_settings->cache_id) {
return;
}
OCIO_GLSLCurveMappping *curvemap = OBJECT_GUARDED_NEW(OCIO_GLSLCurveMappping);
/* Texture. */
allocateCurveMappingTexture(curvemap, curve_mapping_settings);
/* Uniform buffer object. */
curvemap->buffer = GPU_uniformbuf_create(sizeof(OCIO_GLSLCurveMappingParameters));
curvemap->valid = (curvemap->texture != 0);
curvemap->cacheId = 0;
*curvemap_ptr = curvemap;
}
static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap)
{
GPU_texture_free(curvemap->texture);
GPU_uniformbuf_free(curvemap->buffer);
OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping);
}
static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings,
size_t cacheId)
{
/* No need to continue if curvemapping is not used. Just use whatever is in this cache. */
if (curve_mapping_settings == NULL)
return;
if (curvemap->cacheId == cacheId)
return;
if (curvemap->cacheId == 0) {
/* This cache was previously used as dummy. Recreate the texture. */
GPU_texture_free(curvemap->texture);
allocateCurveMappingTexture(curvemap, curve_mapping_settings);
}
curvemap.cache_id = curve_mapping_settings->cache_id;
/* Update texture. */
int offset[3] = {0, 0, 0};
int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
const float *pixels = curve_mapping_settings->lut;
GPU_texture_update_sub(
curvemap->texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));
curvemap.texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));
/* Update uniforms. */
OCIO_GLSLCurveMappingParameters data;
OCIO_GPUCurveMappingParameters data;
for (int i = 0; i < 4; i++) {
data.curve_mapping_range[i] = curve_mapping_settings->range[i];
data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[i];
@ -402,198 +484,193 @@ static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap,
data.curve_mapping_lut_size = curve_mapping_settings->lut_size;
data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate;
GPU_uniformbuf_update(curvemap->buffer, &data);
curvemap->cacheId = cacheId;
GPU_uniformbuf_update(curvemap.buffer, &data);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name LRU cache
/** \name OCIO GPU Shader Implementation
* \{ */
static size_t hash_string(const char *str)
{
size_t i = 0, c;
while ((c = *str++)) {
i = i * 37 + c;
}
return i;
}
static OCIO_GLSLCacheHandle *cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE],
size_t cache_id)
{
OCIO_GLSLCacheHandle *cached_item = &cache[0];
for (int i = 0; i < SHADER_CACHE_SIZE; i++, cached_item++) {
if (cached_item->data == NULL) {
continue;
}
else if (cached_item->cache_id == cache_id) {
/* LRU cache, so move to front. */
OCIO_GLSLCacheHandle found_item = *cached_item;
for (int j = i; j > 0; j--) {
cache[j] = cache[j - 1];
}
cache[0] = found_item;
return &cache[0];
}
}
/* LRU cache, shift other items back so we can insert at the front. */
OCIO_GLSLCacheHandle last_item = cache[SHADER_CACHE_SIZE - 1];
for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
cache[j] = cache[j - 1];
}
/* Copy last to front and let the caller initialize it. */
cache[0] = last_item;
return &cache[0];
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name OCIO GLSL Implementation
* \{ */
/* Detect if we can support GLSL drawing */
bool OCIOImpl::supportGLSLDraw()
bool OCIOImpl::supportGPUShader()
{
/* Minimum supported version 3.3 does meet all requirements. */
return true;
}
static OCIO_GPUDisplayShader &getGPUDisplayShader(
OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings)
{
/* Find existing shader in cache. */
const bool use_curve_mapping = (curve_mapping_settings != nullptr);
for (std::list<OCIO_GPUDisplayShader>::iterator it = SHADER_CACHE.begin();
it != SHADER_CACHE.end();
it++) {
if (it->input == input && it->view == view && it->display == display && it->look == look &&
it->use_curve_mapping == use_curve_mapping) {
/* Move to front of the cache to mark as most recently used. */
if (it != SHADER_CACHE.begin()) {
SHADER_CACHE.splice(SHADER_CACHE.begin(), SHADER_CACHE, it);
}
return *it;
}
}
/* Remove least recently used element from cache. */
if (SHADER_CACHE.size() >= SHADER_CACHE_MAX_SIZE) {
SHADER_CACHE.pop_back();
}
/* Create GPU shader. */
SHADER_CACHE.emplace_front();
OCIO_GPUDisplayShader &display_shader = SHADER_CACHE.front();
display_shader.input = input;
display_shader.view = view;
display_shader.display = display;
display_shader.look = look;
display_shader.use_curve_mapping = use_curve_mapping;
display_shader.valid = false;
/* Create Processors.
*
* Scale and exponent are handled outside of OCIO shader so we can handle them
* as uniforms at the binding stage. OCIO would otherwise bake them into the
* shader code, requiring slow recompiles when interactively adjusting them.
*
* Note that OCIO does have the concept of dynamic properties, however there
* is no dynamic gamma and exposure is part of more expensive operations only.
*
* Since exposure must happen in scene linear, we use two processors. The input
* is usually scene linear already and so that conversion is often a no-op.
*/
OCIO_ConstProcessorRcPtr *processor_to_scene_linear = OCIO_configGetProcessorWithNames(
config, input, ROLE_SCENE_LINEAR);
OCIO_ConstProcessorRcPtr *processor_to_display = OCIO_createDisplayProcessor(
config, ROLE_SCENE_LINEAR, view, display, look, 1.0f, 1.0f);
/* Create shader descriptions. */
if (processor_to_scene_linear && processor_to_display) {
GpuShaderDescRcPtr shaderdesc_to_scene_linear = GpuShaderDesc::CreateShaderDesc();
shaderdesc_to_scene_linear->setLanguage(GPU_LANGUAGE_GLSL_1_3);
shaderdesc_to_scene_linear->setFunctionName("OCIO_to_scene_linear");
(*(ConstProcessorRcPtr *)processor_to_scene_linear)
->getDefaultGPUProcessor()
->extractGpuShaderInfo(shaderdesc_to_scene_linear);
shaderdesc_to_scene_linear->finalize();
GpuShaderDescRcPtr shaderdesc_to_display = GpuShaderDesc::CreateShaderDesc();
shaderdesc_to_display->setLanguage(GPU_LANGUAGE_GLSL_1_3);
shaderdesc_to_display->setFunctionName("OCIO_to_display");
(*(ConstProcessorRcPtr *)processor_to_display)
->getDefaultGPUProcessor()
->extractGpuShaderInfo(shaderdesc_to_display);
shaderdesc_to_display->finalize();
/* Create GPU shader and textures. */
if (createGPUTextures(
display_shader.textures, shaderdesc_to_scene_linear, shaderdesc_to_display) &&
createGPUCurveMapping(display_shader.curvemap, curve_mapping_settings) &&
createGPUShader(display_shader.shader,
display_shader.textures,
shaderdesc_to_scene_linear,
shaderdesc_to_display,
use_curve_mapping)) {
display_shader.valid = true;
}
}
/* Free processors. */
if (processor_to_scene_linear) {
OCIO_processorRelease(processor_to_scene_linear);
}
if (processor_to_display) {
OCIO_processorRelease(processor_to_display);
}
return display_shader;
}
/**
* Setup OpenGL contexts for a transform defined by processor using GLSL
* Setup GPU contexts for a transform defined by processor using GLSL.
* All LUT allocating baking and shader compilation happens here.
*
* Once this function is called, callee could start drawing images
* using regular 2D texture.
*
* When all drawing is finished, finishGLSLDraw shall be called to
* restore OpenGL context to its pre-GLSL draw state.
* When all drawing is finished, gpuDisplayShaderUnbind must be called to
* restore GPU context to its previous state.
*/
bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
OCIO_CurveMappingSettings *curve_mapping_settings,
float dither,
bool use_predivide,
bool use_overlay)
bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings,
const float scale,
const float exponent,
const float dither,
const bool use_predivide,
const bool use_overlay)
{
ConstProcessorRcPtr processor_scene_to_ui = *(ConstProcessorRcPtr *)ocio_processor_scene_to_ui;
ConstProcessorRcPtr processpr_ui_to_display = *(
ConstProcessorRcPtr *)ocio_processor_ui_to_display;
bool use_curve_mapping = curve_mapping_settings != NULL;
if (!processor_scene_to_ui || !processor_scene_to_ui) {
/* Get GPU shader from cache or create new one. */
OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader(
config, input, view, display, look, curve_mapping_settings);
if (!display_shader.valid) {
return false;
}
/* Create state if needed. */
OCIO_GLSLDrawState *state;
if (!*state_r)
*state_r = allocateOpenGLState();
state = *state_r;
/* Verify the shader is valid. */
OCIO_GPUTextures &textures = display_shader.textures;
OCIO_GPUShader &shader = display_shader.shader;
OCIO_GPUCurveMappping &curvemap = display_shader.curvemap;
/* Compute cache IDs. */
GpuShaderDesc shaderDesc;
shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
const char *shader_cache_str = processor_scene_to_ui->getGpuShaderTextCacheID(shaderDesc);
const char *lut3d_cache_str = processor_scene_to_ui->getGpuLut3DCacheID(shaderDesc);
/* Used for comparison. */
std::string shaderCacheID = shader_cache_str;
std::string lut3dCacheID = lut3d_cache_str;
size_t shader_cache_id = hash_string(shader_cache_str);
size_t lut3d_cache_id = hash_string(lut3d_cache_str);
size_t curvemap_cache_id = curve_mapping_settings ? curve_mapping_settings->cache_id : 0;
OCIO_GLSLCacheHandle *shader_handle = cacheSearch(state->shader_cache, shader_cache_id);
OCIO_GLSLCacheHandle *lut3d_handle = cacheSearch(state->lut3d_cache, lut3d_cache_id);
/* We cannot keep more than one cache for curvemap because their cache id is a pointer.
* The pointer cannot be the same for one update but can be the same after a second update. */
OCIO_GLSLCacheHandle *curvemap_handle = &state->curvemap_cache[0];
OCIO_GLSLShader **shader_ptr = (OCIO_GLSLShader **)&shader_handle->data;
OCIO_GLSLLut3d **lut3d_ptr = (OCIO_GLSLLut3d **)&lut3d_handle->data;
OCIO_GLSLCurveMappping **curvemap_ptr = (OCIO_GLSLCurveMappping **)&curvemap_handle->data;
ensureGLSLShader(
shader_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
ensureGLSLLut3d(
lut3d_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
ensureGLSLCurveMapping(curvemap_ptr, curve_mapping_settings);
OCIO_GLSLShader *shader = (OCIO_GLSLShader *)shader_handle->data;
OCIO_GLSLLut3d *shader_lut = (OCIO_GLSLLut3d *)lut3d_handle->data;
OCIO_GLSLCurveMappping *shader_curvemap = (OCIO_GLSLCurveMappping *)curvemap_handle->data;
updateGLSLShader(
shader, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
updateGLSLLut3d(
shader_lut, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, lut3dCacheID);
updateGLSLCurveMapping(shader_curvemap, curve_mapping_settings, curvemap_cache_id);
/* Update handles cache keys. */
shader_handle->cache_id = shader_cache_id;
lut3d_handle->cache_id = lut3d_cache_id;
curvemap_handle->cache_id = curvemap_cache_id;
if (shader->valid && shader_lut->valid && shader_curvemap->valid) {
/* Bind textures to sampler units. Texture 0 is set by caller.
* Uniforms have already been set for texture bind points.*/
if (!use_overlay) {
/* Avoid missing binds. */
GPU_texture_bind(shader_lut->texture_dummy, 1);
}
GPU_texture_bind(shader_lut->texture, 2);
GPU_texture_bind(shader_lut->texture_display, 3);
GPU_texture_bind(shader_curvemap->texture, 4);
/* Bind UBO. */
GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind);
/* TODO(fclem): remove remains of IMM. */
immBindShader(shader->shader);
/* Bind Shader and set uniforms. */
// GPU_shader_bind(shader->shader);
GPU_shader_uniform_float(shader->shader, shader->dither_loc, dither);
GPU_shader_uniform_int(shader->shader, shader->overlay_loc, use_overlay);
GPU_shader_uniform_int(shader->shader, shader->predivide_loc, use_predivide);
GPU_shader_uniform_int(shader->shader, shader->curve_mapping_loc, use_curve_mapping);
return true;
/* Update and bind curve mapping data. */
if (curve_mapping_settings) {
updateGPUCurveMapping(curvemap, curve_mapping_settings);
GPU_uniformbuf_bind(curvemap.buffer, shader.ubo_bind);
GPU_texture_bind(curvemap.texture, TEXTURE_SLOT_CURVE_MAPPING);
}
return false;
/* Bind textures to sampler units. Texture 0 is set by caller.
* Uniforms have already been set for texture bind points.*/
if (!use_overlay) {
/* Avoid missing binds. */
GPU_texture_bind(textures.dummy, TEXTURE_SLOT_OVERLAY);
}
for (int i = 0; i < textures.luts.size(); i++) {
GPU_texture_bind(textures.luts[i].texture, TEXTURE_SLOT_LUTS_OFFSET + i);
}
/* TODO(fclem): remove remains of IMM. */
immBindShader(shader.shader);
/* Bind Shader and set uniforms. */
// GPU_shader_bind(shader.shader);
GPU_shader_uniform_float(shader.shader, shader.scale_loc, scale);
GPU_shader_uniform_float(shader.shader, shader.exponent_loc, exponent);
GPU_shader_uniform_float(shader.shader, shader.dither_loc, dither);
GPU_shader_uniform_int(shader.shader, shader.overlay_loc, use_overlay);
GPU_shader_uniform_int(shader.shader, shader.predivide_loc, use_predivide);
return true;
}
void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
void OCIOImpl::gpuDisplayShaderUnbind()
{
immUnbindProgram();
}
void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state)
void OCIOImpl::gpuCacheFree()
{
for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
if (state->shader_cache[i].data) {
freeGLSLShader((OCIO_GLSLShader *)state->shader_cache[i].data);
}
if (state->lut3d_cache[i].data) {
freeGLSLLut3d((OCIO_GLSLLut3d *)state->lut3d_cache[i].data);
}
if (state->curvemap_cache[i].data) {
freeGLSLCurveMapping((OCIO_GLSLCurveMappping *)state->curvemap_cache[i].data);
}
}
MEM_freeN(state);
SHADER_CACHE.clear();
}
/** \} */

View File

@ -39,8 +39,8 @@ roles:
# Non-color data
data: Non-Color
# CIE XYZ color space
XYZ: XYZ
# For interop between configs, and to determine XYZ for rendering
aces_interchange: Linear ACES
# Specifed by OCIO, not used in Blender
color_timing: Filmic Log
@ -97,7 +97,10 @@ colorspaces:
isdata: false
allocation: lg2
allocationvars: [-8.5, 5]
to_reference: !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse}
from_reference: !<GroupTransform>
children:
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<FileTransform> {src: xyz_to_aces.spimtx, interpolation: linear}
- !<ColorSpace>
name: nuke_rec709

View File

@ -1,3 +0,0 @@
0.9525523959 0.0000000000 0.0000936786 0
0.3439664498 0.7281660966 -0.072132546 0
0.0000000000 0.0000000000 1.0088251844 0

View File

@ -1,3 +0,0 @@
0.4395770431 0.3839148879 0.1765103489 0.0
0.0895979404 0.8147120476 0.0956883803 0.0
0.0174174830 0.1087378338 0.8738504052 0.0

View File

@ -0,0 +1,3 @@
1.0498110175 0.0000000000 -0.0000974845 0
-0.4959030231 1.3733130458 0.0982400361 0
0.0000000000 0.0000000000 0.9912520182 0

View File

@ -32,6 +32,7 @@ extern "C" {
struct ImBuf;
struct OCIO_ConstProcessorRcPtr;
struct OCIO_ConstCPUProcessorRcPtr;
extern float imbuf_luma_coefficients[3];
extern float imbuf_xyz_to_rgb[3][3];
@ -46,8 +47,8 @@ typedef struct ColorSpace {
char name[MAX_COLORSPACE_NAME];
char description[MAX_COLORSPACE_DESCRIPTION];
struct OCIO_ConstProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear;
struct OCIO_ConstCPUProcessorRcPtr *to_scene_linear;
struct OCIO_ConstCPUProcessorRcPtr *from_scene_linear;
bool is_invertible;
bool is_data;
@ -66,8 +67,8 @@ typedef struct ColorManagedDisplay {
char name[MAX_COLORSPACE_NAME];
ListBase views; /* LinkData.data -> ColorManagedView */
struct OCIO_ConstProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear;
struct OCIO_ConstCPUProcessorRcPtr *to_scene_linear;
struct OCIO_ConstCPUProcessorRcPtr *from_scene_linear;
} ColorManagedDisplay;
typedef struct ColorManagedView {

View File

@ -101,40 +101,26 @@ static float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}};
static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER;
typedef struct ColormanageProcessor {
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *cpu_processor;
CurveMapping *curve_mapping;
bool is_data_result;
} ColormanageProcessor;
static struct global_glsl_state {
/* Actual processor used for GLSL baked LUTs. */
/* UI colorspace here refers to the display linear color space,
* i.e: The linear color space w.r.t. display chromaticity and radiometry.
* We separate the colormanagement process into two steps to be able to
* merge UI using alpha blending in the correct color space. */
OCIO_ConstProcessorRcPtr *processor_scene_to_ui;
OCIO_ConstProcessorRcPtr *processor_ui_to_display;
/* Settings of processor for comparison. */
char look[MAX_COLORSPACE_NAME];
char view[MAX_COLORSPACE_NAME];
char display[MAX_COLORSPACE_NAME];
char input[MAX_COLORSPACE_NAME];
float exposure, gamma;
static struct global_gpu_state {
/* GPU shader currently bound. */
bool gpu_shader_bound;
/* Curve mapping. */
CurveMapping *curve_mapping, *orig_curve_mapping;
bool use_curve_mapping;
int curve_mapping_timestamp;
OCIO_CurveMappingSettings curve_mapping_settings;
/* Container for GLSL state needed for OCIO module. */
struct OCIO_GLSLDrawState *ocio_glsl_state;
} global_glsl_state = {NULL};
} global_gpu_state = {NULL};
static struct global_color_picking_state {
/* Cached processor for color picking conversion. */
OCIO_ConstProcessorRcPtr *processor_to;
OCIO_ConstProcessorRcPtr *processor_from;
OCIO_ConstCPUProcessorRcPtr *cpu_processor_to;
OCIO_ConstCPUProcessorRcPtr *cpu_processor_from;
bool failed;
} global_color_picking_state = {NULL};
@ -609,11 +595,10 @@ static void colormanage_free_config(void)
/* free precomputer processors */
if (colorspace->to_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear);
OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)colorspace->to_scene_linear);
}
if (colorspace->from_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear);
OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)colorspace->from_scene_linear);
}
/* free color space itself */
@ -631,11 +616,10 @@ static void colormanage_free_config(void)
/* free precomputer processors */
if (display->to_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->to_scene_linear);
OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)display->to_scene_linear);
}
if (display->from_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->from_scene_linear);
OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)display->from_scene_linear);
}
/* free list of views */
@ -727,35 +711,25 @@ void colormanagement_init(void)
void colormanagement_exit(void)
{
if (global_glsl_state.processor_scene_to_ui) {
OCIO_processorRelease(global_glsl_state.processor_scene_to_ui);
OCIO_gpuCacheFree();
if (global_gpu_state.curve_mapping) {
BKE_curvemapping_free(global_gpu_state.curve_mapping);
}
if (global_glsl_state.processor_ui_to_display) {
OCIO_processorRelease(global_glsl_state.processor_ui_to_display);
if (global_gpu_state.curve_mapping_settings.lut) {
MEM_freeN(global_gpu_state.curve_mapping_settings.lut);
}
if (global_glsl_state.curve_mapping) {
BKE_curvemapping_free(global_glsl_state.curve_mapping);
if (global_color_picking_state.cpu_processor_to) {
OCIO_cpuProcessorRelease(global_color_picking_state.cpu_processor_to);
}
if (global_glsl_state.curve_mapping_settings.lut) {
MEM_freeN(global_glsl_state.curve_mapping_settings.lut);
if (global_color_picking_state.cpu_processor_from) {
OCIO_cpuProcessorRelease(global_color_picking_state.cpu_processor_from);
}
if (global_glsl_state.ocio_glsl_state) {
OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
}
if (global_color_picking_state.processor_to) {
OCIO_processorRelease(global_color_picking_state.processor_to);
}
if (global_color_picking_state.processor_from) {
OCIO_processorRelease(global_color_picking_state.processor_from);
}
memset(&global_glsl_state, 0, sizeof(global_glsl_state));
memset(&global_gpu_state, 0, sizeof(global_gpu_state));
memset(&global_color_picking_state, 0, sizeof(global_color_picking_state));
colormanage_free_config();
@ -777,6 +751,12 @@ static bool colormanage_compatible_look(ColorManagedLook *look, const char *view
return (look->view[0] == 0 || (view_name && STREQ(look->view, view_name)));
}
static bool colormanage_use_look(const char *look, const char *view_name)
{
ColorManagedLook *look_descr = colormanage_look_get_named(look);
return (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_name));
}
void colormanage_cache_free(ImBuf *ibuf)
{
if (ibuf->display_buffer_flags) {
@ -852,95 +832,31 @@ static ColorSpace *display_transform_get_colorspace(
return NULL;
}
static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *look,
const char *view_transform,
const char *display,
float exposure,
float gamma,
const char *from_colorspace,
const bool linear_output)
static OCIO_ConstCPUProcessorRcPtr *create_display_buffer_processor(const char *look,
const char *view_transform,
const char *display,
float exposure,
float gamma,
const char *from_colorspace)
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_DisplayTransformRcPtr *dt;
OCIO_ConstProcessorRcPtr *processor;
ColorManagedLook *look_descr = colormanage_look_get_named(look);
const bool use_look = colormanage_use_look(look, view_transform);
const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure);
const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma);
dt = OCIO_createDisplayTransform();
OCIO_ConstProcessorRcPtr *processor = OCIO_createDisplayProcessor(
config, from_colorspace, view_transform, display, (use_look) ? look : "", scale, exponent);
OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace);
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
if (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_transform)) {
OCIO_displayTransformSetLooksOverrideEnabled(dt, true);
OCIO_displayTransformSetLooksOverride(dt, look);
}
/* fstop exposure control */
if (exposure != 0.0f) {
OCIO_MatrixTransformRcPtr *mt;
float gain = powf(2.0f, exposure);
const float scale4f[] = {gain, gain, gain, 1.0f};
float m44[16], offset4[4];
OCIO_matrixTransformScale(m44, offset4, scale4f);
mt = OCIO_createMatrixTransform();
OCIO_matrixTransformSetValue(mt, m44, offset4);
OCIO_displayTransformSetLinearCC(dt, (OCIO_ConstTransformRcPtr *)mt);
OCIO_matrixTransformRelease(mt);
}
/* post-display gamma transform */
if (gamma != 1.0f) {
OCIO_ExponentTransformRcPtr *et;
float exponent = 1.0f / MAX2(FLT_EPSILON, gamma);
const float exponent4f[] = {exponent, exponent, exponent, exponent};
et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, exponent4f);
OCIO_displayTransformSetDisplayCC(dt, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
}
OCIO_GroupTransformRcPtr *gt = OCIO_createGroupTransform();
OCIO_groupTransformSetDirection(gt, true);
OCIO_groupTransformPushBack(gt, (OCIO_ConstTransformRcPtr *)dt);
if (linear_output) {
/* TODO use correct function display. */
OCIO_ExponentTransformRcPtr *et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, (float[4]){2.2f, 2.2f, 2.2f, 1.0f});
OCIO_groupTransformPushBack(gt, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
}
processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *)gt);
OCIO_groupTransformRelease(gt);
OCIO_displayTransformRelease(dt);
OCIO_configRelease(config);
return processor;
}
if (processor == NULL) {
return NULL;
}
static OCIO_ConstProcessorRcPtr *create_display_encoded_buffer_processor(
const char *UNUSED(display))
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *cpu_processor = OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
/* TODO use correct function display. */
OCIO_ExponentTransformRcPtr *et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, (float[4]){1.0f / 2.2f, 1.0f / 2.2f, 1.0f / 2.2f, 1.0f});
processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
OCIO_configRelease(config);
return processor;
return cpu_processor;
}
static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace,
@ -956,43 +872,54 @@ static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const cha
return processor;
}
static OCIO_ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace)
static OCIO_ConstCPUProcessorRcPtr *colorspace_to_scene_linear_cpu_processor(
ColorSpace *colorspace)
{
if (colorspace->to_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock);
if (colorspace->to_scene_linear == NULL) {
OCIO_ConstProcessorRcPtr *to_scene_linear;
to_scene_linear = create_colorspace_transform_processor(colorspace->name,
global_role_scene_linear);
colorspace->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)to_scene_linear;
OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
colorspace->name, global_role_scene_linear);
if (processor != NULL) {
colorspace->to_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
}
BLI_mutex_unlock(&processor_lock);
}
return (OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear;
return (OCIO_ConstCPUProcessorRcPtr *)colorspace->to_scene_linear;
}
static OCIO_ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace)
static OCIO_ConstCPUProcessorRcPtr *colorspace_from_scene_linear_cpu_processor(
ColorSpace *colorspace)
{
if (colorspace->from_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock);
if (colorspace->from_scene_linear == NULL) {
OCIO_ConstProcessorRcPtr *from_scene_linear;
from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear,
colorspace->name);
colorspace->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)from_scene_linear;
OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
global_role_scene_linear, colorspace->name);
if (processor != NULL) {
colorspace->from_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
}
BLI_mutex_unlock(&processor_lock);
}
return (OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear;
return (OCIO_ConstCPUProcessorRcPtr *)colorspace->from_scene_linear;
}
static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display)
static OCIO_ConstCPUProcessorRcPtr *display_from_scene_linear_processor(
ColorManagedDisplay *display)
{
if (display->from_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock);
@ -1011,16 +938,20 @@ static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManage
OCIO_configRelease(config);
}
display->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor;
if (processor != NULL) {
display->from_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
}
BLI_mutex_unlock(&processor_lock);
}
return (OCIO_ConstProcessorRcPtr *)display->from_scene_linear;
return (OCIO_ConstCPUProcessorRcPtr *)display->from_scene_linear;
}
static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display)
static OCIO_ConstCPUProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display)
{
if (display->to_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock);
@ -1039,13 +970,17 @@ static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedD
OCIO_configRelease(config);
}
display->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor;
if (processor != NULL) {
display->to_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
}
BLI_mutex_unlock(&processor_lock);
}
return (OCIO_ConstProcessorRcPtr *)display->to_scene_linear;
return (OCIO_ConstCPUProcessorRcPtr *)display->to_scene_linear;
}
void IMB_colormanagement_init_default_view_settings(
@ -2168,7 +2103,7 @@ void IMB_colormanagement_transform_v4(float pixel[4],
*/
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) {
/* should never happen */
@ -2176,17 +2111,17 @@ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpac
return;
}
processor = colorspace_to_scene_linear_processor(colorspace);
processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
}
}
/* same as above, but converts colors in opposite direction */
void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) {
/* should never happen */
@ -2194,10 +2129,10 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac
return;
}
processor = colorspace_from_scene_linear_processor(colorspace);
processor = colorspace_from_scene_linear_cpu_processor(colorspace);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
}
}
@ -2205,7 +2140,7 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4],
bool predivide,
ColorSpace *colorspace)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) {
/* should never happen */
@ -2213,14 +2148,14 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4],
return;
}
processor = colorspace_to_scene_linear_processor(colorspace);
processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) {
if (processor != NULL) {
if (predivide) {
OCIO_processorApplyRGBA_predivide(processor, pixel);
OCIO_cpuProcessorApplyRGBA_predivide(processor, pixel);
}
else {
OCIO_processorApplyRGBA(processor, pixel);
OCIO_cpuProcessorApplyRGBA(processor, pixel);
}
}
}
@ -2232,7 +2167,7 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
struct ColorSpace *colorspace,
bool predivide)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) {
/* should never happen */
@ -2240,9 +2175,9 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
return;
}
processor = colorspace_to_scene_linear_processor(colorspace);
processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) {
if (processor != NULL) {
OCIO_PackedImageDesc *img;
img = OCIO_createOCIO_PackedImageDesc(buffer,
@ -2254,10 +2189,10 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
(size_t)channels * sizeof(float) * width);
if (predivide) {
OCIO_processorApply_predivide(processor, img);
OCIO_cpuProcessorApply_predivide(processor, img);
}
else {
OCIO_processorApply(processor, img);
OCIO_cpuProcessorApply(processor, img);
}
OCIO_PackedImageDescRelease(img);
@ -2278,10 +2213,10 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer,
* without precision or performance loss at minimal memory usage. */
BLI_assert(ibuf->rect && ibuf->rect_float == NULL);
OCIO_ConstProcessorRcPtr *processor = NULL;
OCIO_ConstCPUProcessorRcPtr *processor = NULL;
if (compress_as_srgb && ibuf->rect_colorspace &&
!IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) {
processor = colorspace_to_scene_linear_processor(ibuf->rect_colorspace);
processor = colorspace_to_scene_linear_cpu_processor(ibuf->rect_colorspace);
}
/* TODO(brecht): make this multi-threaded, or at least process in batches. */
@ -2294,12 +2229,12 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer,
const unsigned char *in = in_buffer + in_offset * 4;
unsigned char *out = out_buffer + out_offset * 4;
if (processor) {
if (processor != NULL) {
/* Convert to scene linear, to sRGB and premultiply. */
for (int x = 0; x < width; x++, in += 4, out += 4) {
float pixel[4];
rgba_uchar_to_float(pixel, in);
OCIO_processorApplyRGB(processor, pixel);
OCIO_cpuProcessorApplyRGB(processor, pixel);
linearrgb_to_srgb_v3_v3(pixel, pixel);
if (use_premultiply) {
mul_v3_fl(pixel, pixel[3]);
@ -2390,15 +2325,19 @@ void IMB_colormanagement_imbuf_to_float_texture(float *out_buffer,
*/
void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3])
{
if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) {
if (!global_color_picking_state.cpu_processor_to && !global_color_picking_state.failed) {
/* Create processor if none exists. */
BLI_mutex_lock(&processor_lock);
if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) {
global_color_picking_state.processor_to = create_colorspace_transform_processor(
if (!global_color_picking_state.cpu_processor_to && !global_color_picking_state.failed) {
OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
global_role_scene_linear, global_role_color_picking);
if (!global_color_picking_state.processor_to) {
if (processor != NULL) {
global_color_picking_state.cpu_processor_to = OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
else {
global_color_picking_state.failed = true;
}
}
@ -2406,22 +2345,26 @@ void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3])
BLI_mutex_unlock(&processor_lock);
}
if (global_color_picking_state.processor_to) {
OCIO_processorApplyRGB(global_color_picking_state.processor_to, pixel);
if (global_color_picking_state.cpu_processor_to) {
OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_to, pixel);
}
}
void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3])
{
if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) {
if (!global_color_picking_state.cpu_processor_from && !global_color_picking_state.failed) {
/* Create processor if none exists. */
BLI_mutex_lock(&processor_lock);
if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) {
global_color_picking_state.processor_from = create_colorspace_transform_processor(
if (!global_color_picking_state.cpu_processor_from && !global_color_picking_state.failed) {
OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
global_role_color_picking, global_role_scene_linear);
if (!global_color_picking_state.processor_from) {
if (processor != NULL) {
global_color_picking_state.cpu_processor_from = OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
else {
global_color_picking_state.failed = true;
}
}
@ -2429,8 +2372,8 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3])
BLI_mutex_unlock(&processor_lock);
}
if (global_color_picking_state.processor_from) {
OCIO_processorApplyRGB(global_color_picking_state.processor_from, pixel);
if (global_color_picking_state.cpu_processor_from) {
OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_from, pixel);
}
}
@ -2456,24 +2399,20 @@ void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3])
*/
void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor = display_from_scene_linear_processor(display);
processor = display_from_scene_linear_processor(display);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
}
}
/* same as above, but converts color in opposite direction */
void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display)
{
OCIO_ConstProcessorRcPtr *processor;
OCIO_ConstCPUProcessorRcPtr *processor = display_to_scene_linear_processor(display);
processor = display_to_scene_linear_processor(display);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
}
}
@ -3833,13 +3772,13 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(
cm_processor->is_data_result = display_space->is_data;
}
cm_processor->processor = create_display_buffer_processor(applied_view_settings->look,
applied_view_settings->view_transform,
display_settings->display_device,
applied_view_settings->exposure,
applied_view_settings->gamma,
global_role_scene_linear,
false);
cm_processor->cpu_processor = create_display_buffer_processor(
applied_view_settings->look,
applied_view_settings->view_transform,
display_settings->display_device,
applied_view_settings->exposure,
applied_view_settings->gamma,
global_role_scene_linear);
if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
cm_processor->curve_mapping = BKE_curvemapping_copy(applied_view_settings->curve_mapping);
@ -3860,7 +3799,12 @@ ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *f
color_space = colormanage_colorspace_get_named(to_colorspace);
cm_processor->is_data_result = color_space->is_data;
cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace);
OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(from_colorspace,
to_colorspace);
if (processor != NULL) {
cm_processor->cpu_processor = OCIO_processorGetCPUProcessor(processor);
}
OCIO_processorRelease(processor);
return cm_processor;
}
@ -3871,8 +3815,8 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
}
if (cm_processor->processor) {
OCIO_processorApplyRGBA(cm_processor->processor, pixel);
if (cm_processor->cpu_processor) {
OCIO_cpuProcessorApplyRGBA(cm_processor->cpu_processor, pixel);
}
}
@ -3883,8 +3827,8 @@ void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_p
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
}
if (cm_processor->processor) {
OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel);
if (cm_processor->cpu_processor) {
OCIO_cpuProcessorApplyRGBA_predivide(cm_processor->cpu_processor, pixel);
}
}
@ -3894,8 +3838,8 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor,
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
}
if (cm_processor->processor) {
OCIO_processorApplyRGB(cm_processor->processor, pixel);
if (cm_processor->cpu_processor) {
OCIO_cpuProcessorApplyRGB(cm_processor->cpu_processor, pixel);
}
}
@ -3940,7 +3884,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor,
}
}
if (cm_processor->processor && channels >= 3) {
if (cm_processor->cpu_processor && channels >= 3) {
OCIO_PackedImageDesc *img;
/* apply OCIO processor */
@ -3953,10 +3897,10 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor,
(size_t)channels * sizeof(float) * width);
if (predivide) {
OCIO_processorApply_predivide(cm_processor->processor, img);
OCIO_cpuProcessorApply_predivide(cm_processor->cpu_processor, img);
}
else {
OCIO_processorApply(cm_processor->processor, img);
OCIO_cpuProcessorApply(cm_processor->cpu_processor, img);
}
OCIO_PackedImageDescRelease(img);
@ -3986,8 +3930,8 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
if (cm_processor->curve_mapping) {
BKE_curvemapping_free(cm_processor->curve_mapping);
}
if (cm_processor->processor) {
OCIO_processorRelease(cm_processor->processor);
if (cm_processor->cpu_processor) {
OCIO_cpuProcessorRelease(cm_processor->cpu_processor);
}
MEM_freeN(cm_processor);
@ -3995,19 +3939,6 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
static bool check_glsl_display_processor_changed(
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *from_colorspace)
{
return !(global_glsl_state.exposure == view_settings->exposure &&
global_glsl_state.gamma == view_settings->gamma &&
STREQ(global_glsl_state.look, view_settings->look) &&
STREQ(global_glsl_state.view, view_settings->view_transform) &&
STREQ(global_glsl_state.display, display_settings->display_device) &&
STREQ(global_glsl_state.input, from_colorspace));
}
static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
OCIO_CurveMappingSettings *curve_mapping_settings)
{
@ -4041,94 +3972,60 @@ static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
curve_mapping_settings->cache_id = (size_t)curve_mapping + curve_mapping->changed_timestamp;
}
static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *from_colorspace)
static OCIO_CurveMappingSettings *update_glsl_curve_mapping(
const ColorManagedViewSettings *view_settings)
{
bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0;
bool need_update = false;
need_update = global_glsl_state.processor_scene_to_ui == NULL ||
check_glsl_display_processor_changed(
view_settings, display_settings, from_colorspace) ||
use_curve_mapping != global_glsl_state.use_curve_mapping;
if (use_curve_mapping && need_update == false) {
need_update |= view_settings->curve_mapping->changed_timestamp !=
global_glsl_state.curve_mapping_timestamp ||
view_settings->curve_mapping != global_glsl_state.orig_curve_mapping;
/* Using curve mapping? */
const bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0;
if (!use_curve_mapping) {
return NULL;
}
/* Update state if there's no processor yet or
* processor settings has been changed.
*/
if (need_update) {
OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings;
CurveMapping *new_curve_mapping = NULL;
/* Store settings of processor for further comparison. */
BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.display, display_settings->display_device, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.input, from_colorspace, MAX_COLORSPACE_NAME);
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
/* We're using curve mapping's address as a cache ID,
* so we need to make sure re-allocation gives new address here.
* We do this by allocating new curve mapping before freeing old one. */
if (use_curve_mapping) {
new_curve_mapping = BKE_curvemapping_copy(view_settings->curve_mapping);
}
if (global_glsl_state.curve_mapping) {
BKE_curvemapping_free(global_glsl_state.curve_mapping);
MEM_freeN(curve_mapping_settings->lut);
global_glsl_state.curve_mapping = NULL;
curve_mapping_settings->lut = NULL;
}
/* Fill in OCIO's curve mapping settings. */
if (use_curve_mapping) {
curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings);
global_glsl_state.curve_mapping = new_curve_mapping;
global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
global_glsl_state.orig_curve_mapping = view_settings->curve_mapping;
global_glsl_state.use_curve_mapping = true;
}
else {
global_glsl_state.orig_curve_mapping = NULL;
global_glsl_state.use_curve_mapping = false;
}
/* Free old processor, if any. */
if (global_glsl_state.processor_scene_to_ui) {
OCIO_processorRelease(global_glsl_state.processor_scene_to_ui);
}
if (global_glsl_state.processor_ui_to_display) {
OCIO_processorRelease(global_glsl_state.processor_ui_to_display);
}
/* We're using display OCIO processor, no RGB curves yet. */
global_glsl_state.processor_scene_to_ui = create_display_buffer_processor(
global_glsl_state.look,
global_glsl_state.view,
global_glsl_state.display,
global_glsl_state.exposure,
global_glsl_state.gamma,
global_glsl_state.input,
true);
global_glsl_state.processor_ui_to_display = create_display_encoded_buffer_processor(
global_glsl_state.display);
/* Already up to date? */
OCIO_CurveMappingSettings *curve_mapping_settings = &global_gpu_state.curve_mapping_settings;
if (view_settings->curve_mapping->changed_timestamp ==
global_gpu_state.curve_mapping_timestamp &&
view_settings->curve_mapping == global_gpu_state.orig_curve_mapping) {
return curve_mapping_settings;
}
/* Need to update. */
CurveMapping *new_curve_mapping = NULL;
/* We're using curve mapping's address as a cache ID,
* so we need to make sure re-allocation gives new address here.
* We do this by allocating new curve mapping before freeing old one. */
if (use_curve_mapping) {
new_curve_mapping = BKE_curvemapping_copy(view_settings->curve_mapping);
}
if (global_gpu_state.curve_mapping) {
BKE_curvemapping_free(global_gpu_state.curve_mapping);
MEM_freeN(curve_mapping_settings->lut);
global_gpu_state.curve_mapping = NULL;
curve_mapping_settings->lut = NULL;
}
/* Fill in OCIO's curve mapping settings. */
if (use_curve_mapping) {
curve_mapping_to_ocio_settings(new_curve_mapping, &global_gpu_state.curve_mapping_settings);
global_gpu_state.curve_mapping = new_curve_mapping;
global_gpu_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
global_gpu_state.orig_curve_mapping = view_settings->curve_mapping;
global_gpu_state.use_curve_mapping = true;
}
else {
global_gpu_state.orig_curve_mapping = NULL;
global_gpu_state.use_curve_mapping = false;
}
return curve_mapping_settings;
}
bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings))
{
return OCIO_supportGLSLDraw();
return OCIO_supportGPUShader();
}
/**
@ -4165,27 +4062,40 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(
applied_view_settings = &default_view_settings;
}
/* Make sure OCIO processor is up-to-date. */
update_glsl_display_processor(applied_view_settings,
display_settings,
from_colorspace ? from_colorspace->name :
global_role_scene_linear);
/* Ensure curve mapping is up to data. */
OCIO_CurveMappingSettings *curve_mapping_settings = update_glsl_curve_mapping(
applied_view_settings);
if (global_glsl_state.processor_scene_to_ui == NULL) {
/* Happens when requesting non-existing color space or LUT in the
* configuration file does not exist.
*/
return false;
}
/* GPU shader parameters. */
const char *input = from_colorspace ? from_colorspace->name : global_role_scene_linear;
const char *view = applied_view_settings->view_transform;
const char *display = display_settings->display_device;
const bool use_look = colormanage_use_look(applied_view_settings->look,
applied_view_settings->view_transform);
const char *look = (use_look) ? applied_view_settings->look : "";
const float exposure = applied_view_settings->exposure;
const float gamma = applied_view_settings->gamma;
const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure);
const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma);
return OCIO_setupGLSLDraw(
&global_glsl_state.ocio_glsl_state,
global_glsl_state.processor_scene_to_ui,
global_glsl_state.processor_ui_to_display,
global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL,
dither,
predivide,
do_overlay_merge);
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
/* Bind shader. Internally GPU shaders are created and cached on demand. */
global_gpu_state.gpu_shader_bound = OCIO_gpuDisplayShaderBind(config,
input,
view,
display,
look,
curve_mapping_settings,
scale,
exponent,
dither,
predivide,
do_overlay_merge);
OCIO_configRelease(config);
return global_gpu_state.gpu_shader_bound;
}
/* Configures GLSL shader for conversion from scene linear to display space */
@ -4225,8 +4135,9 @@ bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, float dither, bo
/* Finish GLSL-based display space conversion */
void IMB_colormanagement_finish_glsl_draw(void)
{
if (global_glsl_state.ocio_glsl_state != NULL) {
OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state);
if (global_gpu_state.gpu_shader_bound) {
OCIO_gpuDisplayShaderUnbind();
global_gpu_state.gpu_shader_bound = false;
}
}